在SQL Server中限制10..20

我正在尝试做类似的事情:

SELECT * FROM table LIMIT 10,20 

要么

 SELECT * FROM table LIMIT 10 OFFSET 10 

但使用SQL Server

我发现的唯一的解决scheme看起来像过度杀伤:

 SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases ) a WHERE row > 5 and row <= 10 

我还发现 :

 SELECT TOP 10 * FROM stuff; 

…但这不是我想要做的,因为我不能指定起始限制。

有没有另外一种方法可以做到这一点?

此外,只是好奇,是否有一个原因,SQL Server不支持LIMIT函数或类似的东西? 我不想那么卑鄙,但是这听起来像是一个DBMS需要的东西…如果是这样的话,那么我很抱歉如此无知! 我在过去5年一直在使用MySQL和SQL +,所以…

LIMIT子句不是标准SQL的一部分。 它受MySQL,PostgreSQL和SQLite的供应商扩展支持。

其他品牌的数据库可能具有相似的function(例如Microsoft SQL Server中的TOP ),但这些function并不总是一致地工作。

在Microsoft SQL Server中使用TOP很难模仿LIMIT子句。 有些情况下,它不工作。

您使用ROW_NUMBER()显示的解决scheme在Microsoft SQL Server 2005及更高版本中可用。 这是目前最好的解决scheme,只能作为查询的一部分。

另一个解决scheme是使用TOP获取第一个计数 + 偏移行,然后使用API​​来查找第一个偏移行。

也可以看看:

  • “ 在Microsoft SQL Server 2000中模拟MySQL LIMIT子句 ”
  • “ ASP.NET中大型结果集的分页 ”

对于SQL Server 2012 +, 您可以使用 。

 SELECT * FROM sys.databases ORDER BY name OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY 

如你所见,这是首选的sql服务器方法:

 SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases ) a WHERE a.row > 5 and a.row <= 10 

如果您正在使用SQL Server 2012+票选Martin Smith的答案 ,并将OFFSETFETCH NEXT扩展名用于ORDER BY

如果你不幸被卡住了以前的版本,你可以做这样的事情,

 WITH Rows AS ( SELECT ROW_NUMBER() OVER (ORDER BY [dbo].[SomeColumn]) [Row] , * FROM [dbo].[SomeTable] ) SELECT TOP 10 * FROM Rows WHERE Row > 10 

我相信function相当于

 SELECT * FROM SomeTable LIMIT 10 OFFSET 10 ORDER BY SomeColumn 

以及我知道在MS SQL 2012之前使用TSQL执行的最佳方式。


如果有很多行,则可以使用临时表而不是CTE来获得更好的性能。

不幸的是, ROW_NUMBER()是你能做的最好的。 这实际上是更正确的,因为limittop条款的结果在某些特定顺序上并不具有真正意义。 但是这仍然是一件痛苦的事情。

更新:Sql Server 2012通过OFFSET和FETCH关键字添加了一个类似limit的function。

这个怎么样?

 SET ROWCOUNT 10 SELECT TOP 20 * FROM sys.databases ORDER BY database_id DESC 

它给你前20行的最后10行。 一个缺点是顺序颠倒了,但至less很容易记住。

一个好方法是创build一个程序:

 create proc pagination (@startfrom int ,@endto int) as SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (ORDER BY name desc) as row FROM sys.databases ) a WHERE a.row > @startfrom and a.row <= @endto 

就像限制0,2 ///////////////执行分页0,4

只是用于大多数数据库引擎的logging解决scheme可能不是最有效的:

 Select Top (ReturnCount) * From ( Select Top (SkipCount + ReturnCount) * From SourceTable Order By ReverseSortCondition ) ReverseSorted Order By SortCondition 

Pelase注意:无论SkipCount是什么,最后一页仍然会包含ReturnCount行。 但在许多情况下,这可能是件好事。

LIMIT的等价物是SET ROWCOUNT,但是如果你想要generics分页,最好这样写一个查询:

 ;WITH Results_CTE AS ( SELECT Col1, Col2, ..., ROW_NUMBER() OVER (ORDER BY SortCol1, SortCol2, ...) AS RowNum FROM Table WHERE <whatever> ) SELECT * FROM Results_CTE WHERE RowNum >= @Offset AND RowNum < @Offset + @Limit 
 SELECT TOP 10 * FROM TABLE WHERE IDCOLUMN NOT IN (SELECT TOP 10 IDCOLUMN FROM TABLE) 

应该给logging11-20。 可能不是太有效率,如果增加进一步的页面,并不确定如何可能会受到sorting影响。 可能必须在两个WHERE语句中指定它。

 select * from (select id,name,ROW_NUMBER() OVER (ORDER BY id asc) as row from tableName1) tbl1 where tbl1.row>=10 and tbl1.row<=15 

将打印从10到15的行。

到目前为止,这种格式是为我工作(虽然不是最好的performance):

 SELECT TOP {desired amount of rows} * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY {order columns} asc)__row__ FROM {table})tmp WHERE __row__ > {offset row count} 

旁边的一个说明,dynamic数据分页可能会导致奇怪的/意外的结果。

从MS SQL Server联机文档( http://technet.microsoft.com/en-us/library/ms186734.aspx ),这里是他们的示例,我已经testing和工作,检索一组特定的行。 ROW_NUMBER需要OVER,但是您可以按照您喜欢的方式进行订购:

 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; 

使用所有的SQL服务器:;用tbl作为(SELECT ROW_NUMBER()over(order by(select 1))作为RowIndex,*从表中selecttop 10 * from tbl where RowIndex> = 10

  SELECT * FROM users WHERE Id Between 15 and 25 

它将在15至25之间打印MYSQl的限制