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


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 як ту, що в статті, але насправді не пощастило.

Будь-які ідеї, як це реалізувати?

Відповіді:


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

Якщо ми хочемо пропустити ЗАМОВЛЕННЯ, ми можемо використовувати

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

(Я вважаю за краще це як хак - але це використовується, наприклад, NHibernate. Використовувати мудро підібраний стовпчик як ЗАМОВЛЕННЯ - бажаний спосіб)

щоб відповісти на запитання:

--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. Я хочу, щоб ЗАМОВЛЕННЯ відбулося перед БЕРЕГО, оскільки воно в даний час буде сортувати підмножину, але ми хочемо вибрати щось із усього набору ... Будь-які ідеї? :) Ще раз дякую
Ларс Холдгаард

2
Якщо я вас правильно зрозумів, ви б хотіли сортувати за LastDate, правда? тоді ми можемо змінити пункт OVER () таким чином: ROW_NUMBER () OVER (ORDER BY MAX (Datemade) desc ). І видаліть останній ЗАМОВЛЕННЯ PostId . Тепер CTE слід сортувати «швидше» за потребою. правильно?
Радім Келер

1
Дякую, що це допомогло, примітка про зразок 2012 року, замовлення на обов'язкове, я намагався це робити без порядку за допомогою пункту та отримав помилку "неправильний синтаксис", поняття не мав, що не так, доки я не заглянув у синтаксис MSDN і не дізнався, що замовлення є обов'язковим .
Esen

Перший рядок 1 чи 0? Чи БУДЕ WHERE RowNumber >= @Start AND RowNumber < @Endотримати перші 1000 рядків, якщо @Startце 0, а @Endце 1000?
CWS з'являється

1
Дякую велике
Мафій

8

Для того, щоб зробити це на SQL Server, ви повинні замовити запит у стовпці, щоб ви могли вказати потрібні рядки.

Приклад:

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

І при цьому ви не можете використовувати ключове слово "ТОП".

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




-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;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.