【问题标题】:How to select data top x data after y rows from SQL Server如何从 SQL Server 中选择 y 行后的数据 top x 数据
【发布时间】:2011-05-17 12:25:01
【问题描述】:

例如,我有一个包含 10'000 行的表。我想在前 500 行之后选择前 100 行。我怎样才能最有效地做到这一点。

SQL Server 2008 需要查询


例如我已经有这个查询,但我想知道有没有更有效的解决方案

SELECT TOP 100 xx
FROM nn 
WHERE cc NOT IN 
   (SELECT TOP 500 cc
      FROM nn ORDER BY cc ASC)

【问题讨论】:

  • 什么版本的 MS SQL Server?
  • 您的意思是要选择第 500-600 行吗?或者你想要一个结果集返回前 500 行,然后将前 100 行连接到它上面?

标签: sql-server sql-server-2008 select


【解决方案1】:

选择 TOP 500,然后将 TOP 100 连接到结果集。

通常,为了值得这样做,您需要有一些标准来确定您需要 500 条记录的条件,而其他条件只需要 100 条记录。我假设这些条件是 TOP 500 的 condition1,以及您想要的 TOP 100 的 condition2。由于条件不同,这就是为什么根据 TOP 100 的记录可能不一样的原因。

select TOP 500 *
    from MyTable
    where -- condition1 -- Retrieving the first 500 rows meeting condition1
union
    select TOP 100 *
        from MyTable
        where -- condition2 -- Retrieving the first 100 rows meeting condition2
-- The complete result set of the two queries will be combined (UNIONed) into only one result set.

编辑#1

这不是我的意思。我想选择前 500 行之后的前 100 行。所以选择行 501-600

在您发表评论后,我更好地理解了您想要实现的目标。试试这个:

WITH Results AS (
    select TOP 600 f.*, ROW_NUMBER() OVER (ORDER BY f.[type]) as RowNumber
        from MyTable f
) select *
    from Results
    where RowNumber between 501 and 600

这有帮助吗?

【讨论】:

  • 这不是我的意思。我想选择前 500 行之后的前 100 行。所以选择行 501-600
  • 我想要的原因很简单。简单的分页。例如,您有 1000 条记录。但是对于每页显示用户 100。我不想一次选择所有 1000 个结果。
  • 然后你需要选择一个更大的结果集并通过ROW_NUMBER过滤它
  • 是的,这可行,但 Remus Rusanu 所说的似乎更有效率
【解决方案2】:
SELECT 
  col1,
  col2
FROM (
    SELECT ROW_NUMBER() OVER (
        ORDER BY [t0].someColumn) as ROW_NUMBER,
    col1,
    col2
    FROM [dbo].[someTable] AS [t0]
    ) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN 501 and 600
ORDER BY [t1].[ROW_NUMBER]

【讨论】:

  • 对 select 语句中的 select 语句投了反对票。内部选择语句是非常低效的。 IT 进行 RBAR 搜索,simple-talk.com/sql/t-sql-programming/… 如果可以避免(大多数情况下可以)永远不要进行内部选择
  • 我会提出一个问题:为什么?有时这是不可避免的。
  • @Mr.Smith 我粘贴的链接可以比我解释得更好。你是对的,有时这是不可避免的,但那些时间很少而且相距甚远。例如,@Remus Rusanu 显示使用 cte(通用表表达式)会更好,因为它以不同的方式进行表扫描。我推荐阅读 RBAR sql 表达式。
  • @george9170,我已经将@Remus Rusanu 的方法与我自己的方法进行了比较。执行计划和我一模一样。
  • @george9170,您发布的链接并没有让我清楚我的查询是如何效率低下的。我可以看到我是否在 SELECT 子句中执行 SELECT,但我正在 FROM 子句中执行内联查询。您是否有任何其他资源可以解释 RBAR 条件?性能似乎与@Remus 的解决方案相同。
【解决方案3】:
Select T0P 600 * 
from my table
where --whatever condition you want
except
select top 500 * 
from mytable
where --whatever condition you want

【讨论】:

  • 这似乎是最好的答案,除了我们必须两次给出相同的 where 条件。
【解决方案4】:

Tutorial 25: Efficiently Paging Through Large Amounts of Data

with cte as (
 SELECT ...,
  ROW_NUMBER () OVER (ORDER BY ...) as rn
 FROM ...)
SELECT ... FROM cte 
WHERE rn BETWEEN 500 and 600;

【讨论】:

  • 我们能说这是最有效的方法吗?
  • 没有。即使在最好的情况下,这仍然必须扫描 500 行以计算它们,以便知道何时开始。在更糟糕的情况下,它需要扫描所有行,对它们进行排序,然后计算 500 个已排序的行以到达起点。如果您要求第 9500 到 10000 行,情况会变得更糟,然后更糟的是第 999500 到 1000000 行。最有效的方法是键集驱动:SELECT TOP(500) ... FROM ... WHERE key > @lastPageLastKey,但这需要客户端中的奇特逻辑(跟踪键)和不允许任意列顺序。
  • 我明白了。但这对我来说是不可能的,因为有过滤功能。
猜你喜欢
  • 2015-11-04
  • 2011-03-17
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多