【问题标题】:Selecting n Number of Rows Starting From The nth Row [duplicate]选择从第 n 行开始的 n 行 [重复]
【发布时间】:2013-07-29 17:39:16
【问题描述】:

这里的 SQL-noobie 想要将以下存储过程修改为从指定行开始选择指定数量行的存储过程。比如我想从第10行开始选择5行,即10、11、12、13、14、15。

这是我的 SP 在 atm 的样子:

SELECT Posts.Slug, Comments.commentId, Comments.[date], Comments.name, Comments.[text]
FROM Comments 
INNER JOIN Posts ON Comments.postId = Posts.Id
WHERE Comments.approved = 0

我不需要对结果进行排序,因为我想按顺序阅读,以防万一。

谢谢!

【问题讨论】:

  • 你认为“依次”是什么意思?按什么排序?
  • 你想要的也叫paging
  • 在您的情况下,顺序确实很重要,因为没有顺序,结果可能因不同的执行而异。你基本上是在寻找分页。在这种情况下,您只需要订购,然后使用 RowNum 获取切片:stackoverflow.com/questions/109232/…
  • “我不需要对结果进行排序,因为我想按顺序阅读,以防万一”这句话自相矛盾,你最好删除它。
  • SQL Server 不维护它们在数据库中的存储顺序。考虑一个表,一个无序的行包。如果您想按某些东西订购,您需要告诉 SQL Server 那是什么。在这种情况下,我假设[date],只要这只是一个糟糕的名字,它实际上也包括时间。

标签: sql sql-server tsql


【解决方案1】:

如 Maurice 所述,在 SQL Server 2005/2008 中,您需要使用行号。不幸的是,LIMIT 语法不起作用。查询将如下所示(假设您要按日期排序)

WITH numbered AS
(
    SELECT 
       Posts.Slug, 
       Comments.commentId, 
       Comments.[date],
       Comments.name, Comments.[text],  
       ROW_NUMBER() OVER (ORDER BY date) as rownum
    FROM Comments 
    INNER JOIN Posts ON Comments.postId = Posts.Id
    WHERE Comments.approved = 0
) 
SELECT * FROM numbered WHERE rownum BETWEEN @startrow AND @endrow

以上假设@startrow 和@endrow 是传递给您的存储过程的参数。

【讨论】:

  • 谢谢它的工作,我只需要更改最后一部分,因为我不想选择rownum :)。
【解决方案2】:

如果您碰巧使用的是 SQL Server 2012,则可以使用 OFFSETFETCH 进行分页,但它们需要 ORDER BY 子句:

SELECT Posts.Slug, Comments.commentId, Comments.[date], Comments.name, Comments.[text]
FROM Comments 
INNER JOIN Posts ON Comments.postId = Posts.Id
WHERE Comments.approved = 0
ORDER BY [date]
OFFSET 10 ROWS
FETCH NEXT 5 ROWS ONLY

如果不使用 SQL Server 2012,您应该采用 ROW_NUMBER() 方法。

如果你真的想要任意排序,你可以使用ORDER BY (SELECT 1),但是没有明确的排序就不能保证一致性。

【讨论】:

  • 感谢您的回答,但我决定使用ROW_NUMBER() 以获得更好的兼容性。仍然如此工作如此欢呼!
【解决方案3】:

确实对于sql server来说最快的是

SELECT col1, col2 
FROM (
    SELECT col1, col2, ROW_NUMBER() OVER (ORDER BY ID) AS RowNum
    FROM MyTable
) AS MyDerivedTable
WHERE MyDerivedTable.RowNum BETWEEN @startRow AND @endRow

看看here

【讨论】:

  • 这在功能上与 Daniel Neal 的回答没有什么不同
  • @swasheck 实际上并不相同。我已经为您添加了参考,以供您进一步阅读和理解该声明。还是很抱歉
  • 它有什么不同,除了您使用派生表而不是 CTE,而且您没有费心使用 OP 的实际表名?
  • 没有难过的感觉我搜索到stackoverflow并找到了这个:stackoverflow.com/questions/187998/row-offset-in-sql-server所以我这个问题是重复的。赖特?
  • 是的。这就是我们 VtC 的原因。
【解决方案4】:

在 t-sql 中使用 ROW_NUMBER() 函数。见MSDN

USE AdventureWorks2012;
GO
WITH OrderedOrders AS
(
    SELECT SalesOrderID, OrderDate,
    ROW_NUMBER() OVER (ORDER BY OrderDate) AS RowNumber
    FROM Sales.SalesOrderHeader 
) 
SELECT SalesOrderID, OrderDate, RowNumber  
FROM OrderedOrders 
WHERE RowNumber BETWEEN 50 AND 60;

【讨论】:

    猜你喜欢
    • 2020-02-14
    • 2020-07-27
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-06
    相关资源
    最近更新 更多