SQLServer 中的 LIMIT10..20

我想做的是:

SELECT * FROM table LIMIT 10,20

或者

SELECT * FROM table LIMIT 10 OFFSET 10

而是使用 SQLServer

唯一的 我找到的解决办法看起来像是过度杀戮:

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;

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

还有别的办法吗?

另外,只是好奇,是否有一个原因为什么 SQLServer 不支持 LIMIT函数或类似的东西?我不想这么刻薄,但是这听起来确实像是 DBMS 需要的东西... ... 如果是这样的话,那么我为我的无知感到抱歉!在过去的5年里,我一直在使用 MySQL 和 SQL + ,所以..。

363228 次浏览

不幸的是,ROW_NUMBER()是你能做的最好的。它实际上更正确,因为如果不考虑某些特定的顺序,limittop子句的结果实际上没有意义。但还是很痛苦。

更新: Sql Server 2012通过 OffSET 和 FETCH 关键字增加了一个类似于 limit的特性。与非标准 MySql 扩展 LIMIT相反,这是 ansi 标准方法。

正如您所发现的,这是首选的 sql 服务器方法:

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

这个怎么样?

SET ROWCOUNT 10


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

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

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

其他品牌的数据库可能有类似的功能(例如 Microsoft SQL Server 中的 TOP) ,但这些功能并不总是完全相同。

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

你展示的使用 ROW_NUMBER()的解决方案在2005年 Microsoft SQL Server 及以后都可以使用。这是目前仅作为查询的一部分工作的最佳解决方案。

另一种解决方案是使用 TOP获取第一个 计数 + 偏移行,然后使用 API 寻找第一个 偏移行之后的行。

参见:

SELECT TOP 10 *
FROM TABLE
WHERE IDCOLUMN NOT IN (SELECT TOP 10 IDCOLUMN FROM TABLE)

记录应该是11-20。 如果增量以获取更多页面,可能效率不太高,而且不确定排序会对其产生什么影响。 可能必须在两个 WHERE 语句中指定这一点。

用于 SQLServer2012 + 你可以利用

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

如果您使用 SQLServer2012 + 为 马丁 · 史密斯的回答投票,并使用 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

我相信在功能上等同于

SELECT * FROM SomeTable LIMIT 10 OFFSET 10 ORDER BY SomeColumn

以及我所知道的在 TSQL 中做到这一点的最佳方式,在 MSSQL 2012之前。


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

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的行。

到目前为止,这种格式对我有效(尽管不是最好的性能) :

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}

另外,对动态数据进行分页可能导致奇怪/意外的结果。

从 MS SQL Server 在线文档(< a href = “ http://technet.microsoft.com/en-us/library/ms186734.aspx”rel = “ nofollow”> http://technet.microsoft.com/en-us/library/ms186734.aspx ) ,这里是他们的例子,我已经测试和工作,检索一组特定的行。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;

一个好的方法是创建一个过程:

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

使用所有 SQL 服务器: ; tbl 为(SELECT ROW _ NUMBER () over (order by (SELECT 1))为 RowIndex,* from table) 从 tbl 中选择 top 10 * ,其中 RowIndex > = 10

 SELECT * FROM users WHERE Id Between 15 and 25

它将打印从15至25作为类似的限制在 MYSQL

只是针对大多数数据库引擎的记录解决方案,虽然可能不是最有效的:

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

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

LIMIT 的等价物是 SET ROWCOUNT,但是如果您想要通用分页,最好编写如下查询:

;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