在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的答案 ,并将OFFSET
和FETCH 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()
是你能做的最好的。 这实际上是更正确的,因为limit
或top
条款的结果在某些特定顺序上并不具有真正意义。 但是这仍然是一件痛苦的事情。
更新: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的限制