Как написать LINQ.Skip(1000). Захватить (100) в чистом SQL?

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

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

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

Ответ 1

В 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

Ответ 2

SQL Server 2012 и выше добавили этот синтаксис:

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

Ответ 3

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 строк, прежде чем запускать для возврата результатов. Слишком часто разработчики забывают об этом и просто бросают контроль над страницами на стол с пятью тысячами строк и задаются вопросом, почему первая страница возвращается намного быстрее, чем последняя...

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

Ответ 4

Попробуйте следующее:

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

Ответ 5

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

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

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

Ответ 7

Я использую что-то вроде этого, чтобы выбрать первые 100, пропускающие первую 1000.

SELECT TOP(100) * 
FROM MY_TABLE 
WHERE ID not in (SELECT TOP(1000) ID From My_TABLE);

Вам нужно использовать одно и то же предложение where, если вы хотите фильтровать больше результатов:

SELECT TOP(100) * 
FROM MY_TABLE 
WHERE WHERE Status = 'P' AND
ID not in (SELECT TOP(1000) ID From My_TABLE WHERE Status = 'P');