如何用Microsoft SQL Server实现LIMIT?

我有这个查询与MySQL:

select * from table1 LIMIT 10,20 

我怎样才能做到这一点与微软的SQL?

启动SQL SERVER 2005,你可以这样做…

 USE AdventureWorks; GO WITH OrderedOrders AS ( SELECT SalesOrderID, OrderDate, ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber' FROM Sales.SalesOrderHeader ) SELECT * FROM OrderedOrders WHERE RowNumber BETWEEN 10 AND 20; 

或者这样的2000年和以下的版本…

 SELECT TOP 10 * FROM (SELECT TOP 20 FROM Table ORDER BY Id) ORDER BY Id DESC 

笨重,但它会工作。

 SELECT TOP 10 * FROM table WHERE id NOT IN (SELECT TOP 10 id FROM table ORDER BY id) FROM table ORDER BY id 

国际海事组织(MSO)对LIMIT条款的省略是犯罪行为。 你不应该做这种解决方法。

这几乎是我在十月份提出的一个问题的重复: 模仿Microsoft SQL Server 2000中的MySQL LIMIT子句

如果您使用的是Microsoft SQL Server 2000,那么没有好的解决scheme。 大多数人不得不求助于在具有IDENTITY主键的临时表中捕获查询的结果。 然后使用BETWEEN条件对主键列进行查询。

如果您使用的是Microsoft SQL Server 2005或更高版本,则具有ROW_NUMBER()函数,因此您可以得到相同的结果,但避免使用临时表。

 SELECT t1.* FROM ( SELECT ROW_NUMBER OVER(ORDER BY id) AS row, t1.* FROM ( ...original SQL query... ) t1 ) t2 WHERE t2.row BETWEEN @offset+1 AND @offset+@count; 

你也可以把它写成@Leon Tayson的答案中所示的公共表格expression式 。

从SQL SERVER 2012开始,您可以使用OFFSET FETCH子句:

 USE AdventureWorks; GO SELECT SalesOrderID, OrderDate FROM Sales.SalesOrderHeader ORDER BY SalesOrderID OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY; GO 

http://msdn.microsoft.com/en-us/library/ms188385(v=sql.110).aspx

当顺序不唯一时,这可能无法正常工作。

如果查询被修改为ORDER BY OrderDate,则返回的结果集不符合预期。

 SELECT * FROM ( SELECT TOP 20 t.*, ROW_NUMBER() OVER (ORDER BY field1) AS rn FROM table1 t ORDER BY field1 ) t WHERE rn > 10 

语法MySQL LIMIT查询是这样的:

 SELECT * FROM table LIMIT OFFSET, ROW_COUNT 

这可以被翻译成Microsoft SQL Server就好

 SELECT * FROM ( SELECT TOP #{OFFSET+ROW_COUNT} *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum FROM table ) a WHERE rnum > OFFSET 

现在你的查询select * from table1 LIMIT 10,20将是这样的:

 SELECT * FROM ( SELECT TOP 30 *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum FROM table1 ) a WHERE rnum > 10 

这是我如何限制MS SQL Server 2012中的结果

 SELECT * FROM table1 ORDER BY columnName OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY 

注意:OFFSET只能与ORDER BY一起使用或一起使用。

解释代码行OFFSET xx ROWS FETCH NEXT yy ROW ONLY

“xx”是您想要从表中开始提取的logging/行号。
IE:如果表1中有40条logging,则上面的代码将从第10行开始。

“yy”是您想要从表中拉出的logging/行数。
build立在前面的例子上。
IE:如果表1有40条logging,并且您从第10行开始拉动并抓取10(yy)的下一个集合。
这意味着,上面的代码将从第1行开始,第10行结束于20,从而拉动第10-20行。

查看链接了解关于OFFSET的更多信息

这是我试图避免使用MS服务器的原因之一…但无论如何。 有时你只是没有select(ye!我必须使用过时的版本!!)。

我的build议是创build一个虚拟表:

从:

 SELECT * FROM table 

至:

 CREATE VIEW v_table AS SELECT ROW_NUMBER() OVER (ORDER BY table_key) AS row,* FROM table 

然后只是查询:

 SELECT * FROM v_table WHERE row BETWEEN 10 AND 20 

如果添加或删除字段,则“行”会自动更新。

这个选项的主要问题是ORDER BY是固定的。 所以,如果你想要一个不同的顺序,你将不得不创build另一个视图。

UPDATE

这种方法还有另一个问题:如果您尝试过滤数据,它将无法按预期工作。 例如,如果你这样做:

 SELECT * FROM v_table WHERE field = 'test' AND row BETWEEN 10 AND 20 

WHERE变得局限于10到20行之间的数据(而不是search整个数据集并限制输出)。

这是一个可以在SQL2000中工作的多步骤方法。

 -- Create a temp table to hold the data CREATE TABLE #foo(rowID int identity(1, 1), myOtherColumns) INSERT INTO #foo (myColumns) SELECT myData order By MyCriteria Select * FROM #foo where rowID > 10 
 SELECT * FROM ( SELECT top 20 -- ($a) number of records to show * FROM ( SELECT top 29 -- ($b) last record position * FROM table -- replace this for table name (ie "Customer") ORDER BY 2 ASC ) AS tbl1 ORDER BY 2 DESC ) AS tbl2 ORDER BY 2 ASC; -- Examples: -- Show 5 records from position 5: -- $a = 5; -- $b = (5 + 5) - 1 -- $b = 9; -- Show 10 records from position 4: -- $a = 10; -- $b = (10 + 4) - 1 -- $b = 13; -- To calculate $b: -- $b = ($a + position) - 1 -- For the present exercise we need to: -- Show 20 records from position 10: -- $a = 20; -- $b = (20 + 10) - 1 -- $b = 29; 

如果我没有记错的话(从我用SQL Server开始已经有一段时间了),你可以使用类似这样的方法:(2005年及以后)

 SELECT * ,ROW_NUMBER() OVER(ORDER BY SomeFields) AS [RowNum] FROM SomeTable WHERE RowNum BETWEEN 10 AND 20 
 SELECT TOP 10 * FROM table; 

是相同的

 SELECT * FROM table LIMIT 0,10; 

这里有一篇关于在MsSQL中实现Limit的文章它是一个很好的阅读,特别是评论。