Как мне написать LINQ .Skip (1000) .Take (100) на чистом SQL? - PullRequest
91 голосов
/ 16 ноября 2009

Что такое SQL-эквивалент метода .Skip() в LINQ?

Например: я хотел бы выбрать строки 1000-1100 из определенной таблицы базы данных.

Это возможно только с SQL? Или мне нужно выбрать всю таблицу, а затем найти строки в памяти? В идеале я бы хотел этого избежать, если это возможно, поскольку таблица может быть довольно большой.

Ответы [ 6 ]

134 голосов
/ 30 октября 2013

SQL Server 2012 и выше добавили следующий синтаксис:

SELECT *
FROM Sales.SalesOrderHeader 
ORDER BY OrderDate
OFFSET (@Skip) ROWS FETCH NEXT (@Take) ROWS ONLY
77 голосов
/ 17 ноября 2009

В 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
22 голосов
/ 17 ноября 2009

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;

Это работает, но необходимость получения row_number из ORDER BY может привести к сортировке вашего запроса на стороне сервера и вызвать проблемы с производительностью. Даже если индекс может удовлетворить требование ORDER BY, запрос все равно должен посчитать 1000 строк, прежде чем начать возвращать результаты. Слишком часто разработчики забывают об этом и просто запускают элемент управления разбиением на страницы над таблицей 5 миллионов строк и задаются вопросом, почему первая страница возвращается намного быстрее, чем последняя ...

Тем не менее использование ROW_NUMBER (), вероятно, является наилучшим балансом между простотой использования и хорошей производительностью при условии, что вы избегаете сортировки (условие ORDER BY может быть удовлетворено индексом).

4 голосов
/ 23 сентября 2016

Попробуйте это:

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 голосов
/ 17 ноября 2009

Сделайте это:

Запустите .Skip (1000). Возьмите (100) в текстовом формате LINQ to SQL и посмотрите на вывод SQL. Он сгенерирует для вас оператор SQL, который делает то, что вы описываете.

Это не будет так элегантно, но оно выполнит свою работу.

2 голосов
/ 16 ноября 2009

Нет, но вы можете эмулировать предложение LIMIT MySQL (ссылка переполнения стека) для достижения того же результата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...