15

我正在寻找这样的表达式(使用 SQL Server 2008)

SELECT TOP 10 columName FROM tableName

但我需要 10 到 20 之间的值而不是那个值。我想知道是否有一种方法可以只使用一个 SELECT 语句来做到这一点。

例如这是没用的:

SELECT columName FROM
(SELECT ROW_NUMBER() OVER(ORDER BY someId) AS RowNum, * FROM tableName) AS alias
WHERE RowNum BETWEEN 10 AND 20

因为括号内的选择已经返回所有结果,我希望避免这种情况,因为性能。

4

5 回答 5

10

有一个技巧row_number不涉及对所有行进行排序。

尝试这个:

SELECT columName
FROM (SELECT ROW_NUMBER() OVER(ORDER BY (select NULL as noorder)) AS RowNum, *
      FROM tableName
     ) as alias
WHERE RowNum BETWEEN 10 AND 20

您不能在order by. 但是,您可以使用计算结果为常量的表达式。SQL Server 认识到这一点,并仅返回遇到的行,并正确枚举。

于 2012-11-16T19:00:27.057 回答
8

使用 SQL Server 2012 获取/跳过!

SELECT SalesOrderID, SalesOrderDetailID, ProductID, OrderQty, UnitPrice, LineTotal
FROM AdventureWorks2012.Sales.SalesOrderDetail
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;

对于旧版本的 sql server,没有什么比您描述的更好的了。也许使用 CTE,但不太可能有所作为。

WITH NumberedMyTable AS
(
    SELECT
        Id,
        Value,
        ROW_NUMBER() OVER (ORDER BY Id) AS RowNumber
    FROM
        MyTable
)
SELECT
    Id,
    Value
FROM
    NumberedMyTable
WHERE 
    RowNumber BETWEEN @From AND @To  

或者,您可以删除前 10 行,然后获取接下来的 10 行,但我会加倍任何人想要这样做。

于 2012-11-16T18:55:23.283 回答
3

为什么你认为 SQL Server 会评估整个内部查询?假设您的排序列已编入索引,它只会读取前 20 个值。如果你真的很紧张,你可以这样做:

Select
  Id 
From (
  Select Top 20 -- note top 20
    Row_Number() Over(Order By Id) As RowNum,
    Id 
  From
    dbo.Test
  Order By
    Id
  ) As alias
Where
  RowNum Between 10 And 20
Order By
  Id

但我很确定查询计划是相同的。

(真的)根据 Aaron 的评论修复。

http://sqlfiddle.com/#!3/db162/6

于 2012-11-16T19:07:05.163 回答
1

另一种选择

SELECT TOP(11) columName
FROM dbo.tableName
ORDER BY
CASE WHEN ROW_NUMBER() OVER (ORDER BY someId) BETWEEN 10 AND 20 
     THEN ROW_NUMBER() OVER (ORDER BY someId) ELSE NULL END DESC
于 2012-11-17T14:53:27.237 回答
0

您可以创建一个按您想要的方式排序的临时表:

SELECT ROW_NUMBER() OVER(ORDER BY someId) AS RowNum, * FROM tableName into ##tempTable ...

这样你就有了一个有序的行列表。并且可以在随后的时间中只按行号查询,而不是多次进行内部查询。

于 2014-06-16T19:18:35.337 回答