Реализовать функциональность подкачки (пропустить / взять) с этим запросом

138

Я пытался понять немного о том, как реализовать пользовательский пейджинг в SQL, например, читая статьи, подобные этой .

У меня есть следующий запрос, который отлично работает. Но я хотел бы реализовать пейджинг с этим.

SELECT TOP x PostId FROM ( SELECT PostId, MAX (Datemade) as LastDate
 from dbForumEntry 
 group by PostId ) SubQueryAlias
 order by LastDate desc

Что это я хочу

У меня есть сообщения на форуме, с соответствующими записями. Я хочу получать сообщения с последними добавленными записями, чтобы выбрать недавно обсужденные сообщения.

Теперь я хочу получить «10 из 20 последних активных сообщений» вместо «10 лучших».

Что я пробовал

Я попытался реализовать функции ROW, как в статье, но на самом деле безуспешно.

Есть идеи как это реализовать?

Lars Holdgaard
источник

Ответы:

288

В SQL Server 2012 это очень легко

SELECT col1, col2, ...
 FROM ...
 WHERE ... 
 ORDER BY -- this is a MUST there must be ORDER BY statement
-- the paging comes here
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

Если мы хотим пропустить ORDER BY, мы можем использовать

SELECT col1, col2, ...
  ...
 ORDER BY CURRENT_TIMESTAMP
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

(Я бы предпочел пометить это как хак - но он используется, например, NHibernate. Использовать мудро подобранный столбец в качестве ORDER BY является предпочтительным способом)

ответить на вопрос:

--SQL SERVER 2012
SELECT PostId FROM 
        ( SELECT PostId, MAX (Datemade) as LastDate
            from dbForumEntry 
            group by PostId 
        ) SubQueryAlias
 order by LastDate desc
OFFSET 10 ROWS -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

Новые ключевые слова offsetи fetch next(только следуя стандартам SQL) были введены.

Но я предполагаю, что вы не используете SQL Server 2012 , верно ? В предыдущей версии это немного (немного) сложно. Вот сравнение и примеры для всех версий SQL сервера: здесь

Итак, это может работать в SQL Server 2008 :

-- SQL SERVER 2008
DECLARE @Start INT
DECLARE @End INT
SELECT @Start = 10,@End = 20;


;WITH PostCTE AS 
 ( SELECT PostId, MAX (Datemade) as LastDate
   ,ROW_NUMBER() OVER (ORDER BY PostId) AS RowNumber
   from dbForumEntry 
   group by PostId 
 )
SELECT PostId, LastDate
FROM PostCTE
WHERE RowNumber > @Start AND RowNumber <= @End
ORDER BY PostId
Радим Келер
источник
Большое спасибо! Это действительно хороший ответ! Только вопрос о SQL 2008. Я хочу, чтобы ORDER BY происходил до WHERE, поскольку в данный момент он будет сортировать подмножество, но мы хотим выбрать что-то из всего набора ... Есть идеи? :) Еще раз спасибо
Lars Holdgaard
2
Если я вас правильно понимаю, вы хотите отсортировать по LastDate, верно? тогда мы можем изменить предложение OVER () следующим образом: ROW_NUMBER () OVER (ORDER BY MAX (Datemade) desc ). И удалите последний ORDER BY PostId . Теперь CTE должен быть отсортирован «раньше» по мере необходимости. верный?
Радим Келер
1
Спасибо, это помогло, заметка о образце 2012 года, упорядочение по обязательному, я пробовал это без упорядочения по пункту и получил ошибку «неправильный синтаксис», понятия не имел, что не так, пока я не изучил синтаксис MSDN и не узнал, что упорядочение по является обязательным ,
Esen
Первый ряд 1 или 0? Если ГДЕ WHERE RowNumber >= @Start AND RowNumber < @Endполучить первые 1000 строк, если @Start0 и @End1000?
CWSpear
1
Большое спасибо
Мафия
8

Чтобы сделать это в SQL Server, необходимо упорядочить запрос по столбцу, чтобы можно было указать нужные строки.

Пример:

select * from table order by [some_column] 
offset 10 rows
FETCH NEXT 10 rows only

И вы не можете использовать ключевое слово "TOP" при этом.

Вы можете узнать больше здесь: https://technet.microsoft.com/pt-br/library/gg699618%28v=sql.110%29.aspx

Фелипе В.Р.
источник
5
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

используйте это в конце вашего выбора синтаксиса. знак равно

Николас Виниций Срочински
источник
5

SQL 2008

Ответ Радима Келера работает, но вот более короткая версия:

select top 20 * from
(
select *,
ROW_NUMBER() OVER (ORDER BY columnid) AS ROW_NUM
from tablename
) x
where ROW_NUM>10

Источник: https://forums.asp.net/post/4033909.aspx

Tadej
источник
-1

Вы можете использовать вложенный запрос для разбивки на страницы следующим образом:

Пейджинг от 4 строки до 8 строки, где CustomerId является первичным ключом .

SELECT Top 5 * FROM Customers
WHERE Country='Germany' AND CustomerId Not in (SELECT Top 3 CustomerID FROM Customers
WHERE Country='Germany' order by city) 
order by city;
amoljdv06
источник