如何用纯SQL编写LINQ的.Skip(1000).Take(100)?


93

.Skip()LINQ中与该方法等效的SQL是什么?

例如:我想从特定的数据库表中选择1000-1100行。

仅使用SQL可能吗?还是我需要选择整个表,然后在内存中查找行?理想情况下,我希望避免这种情况,因为表可能会很大。

Answers:


78

在SQL Server 2005及更高版本中,可以使用ROW_NUMBER函数。例如。

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 51 AND 60; --BETWEEN is inclusive

有关更多详细信息,请参见我的答案中的链接。stackoverflow.com/questions/1744802/...
麦克阿特拉斯

在51和60之间-包括在内。
Drew Miller

1
但这将首先选择所有内容,然后从该选择中只选择10个,对吗?还是第一个查询/视图已经只有10个?
塔德伊

138

SQL Server 2012及更高版本添加了以下语法:

SELECT *
FROM Sales.SalesOrderHeader 
ORDER BY OrderDate
OFFSET (@Skip) ROWS FETCH NEXT (@Take) ROWS ONLY

11
请注意,您需要使用ORDER BY ___才能使用OFFSET命令...。不是您应该尝试不使用命令进行分页。
詹姆斯·豪格

另请注意,“ new”语法奇怪地具有与@skip线性相关的性能损失!row_number方法不具有此功能(仅按索引顺序进行测试)。对于lo @Skip小于约20,新语法比row_number方法快。
Eske Rahn

22

LINQ to SQL通过使用ROW_NUMBER窗口函数来做到这一点:

  SELECT a,b,c FROM 
   (SELECT a,b,c, ROW_NUMBER() OVER (ORDER BY ...) as row_number
    FROM Table) t0
   WHERE to.row_number BETWEEN 1000 and 1100;

这行得通,但是需要从ORDER BY中制造row_number 可能会导致您的查询在服务器端被排序并导致性能问题。即使索引可以满足ORDER BY要求,查询仍然必须计数1000行才能开始返回结果。开发人员常常忘记了这一点,只对500万行表进行了分页控制,想知道为什么首页返回的速度比最后一页快得多...

尽管如此,使用ROW_NUMBER()可能是在易用性和良好性能之间的最佳平衡,前提是您要确保避免排序(索引可以满足ORDER BY条件)。


1
感谢您提供额外的性能信息,请务必谨慎并进行测试。

经过测试,对于我的50万行表,最后一页比第一页慢7倍。不理想,但对我来说可以接受。

6

试试这个:

select * from [Table-Name] order by [Column-Name] 
offset [Skip-Count] rows
FETCH NEXT [Take-Count] rows only

例:

select * from Personals order by Id
offset 10 rows            --------->Skip 10
FETCH NEXT 15 rows only   --------->Take 15

4

做这个:

在LINQ to SQL数据上下文上运行.Skip(1000).Take(100),然后查看SQL输出。它将为您生成执行您所描述的SQL语句。

它不会那么优雅,但是可以完成工作。


2
没有问什么。
RayLoveless 2013年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.