Zaimplementuj funkcję stronicowania (pomiń / pobierz) za pomocą tego zapytania

138

Próbowałem trochę zrozumieć, jak zaimplementować niestandardowe stronicowanie w SQL, na przykład czytając artykuły takie jak ten .

Mam następujące zapytanie, które działa idealnie. Ale chciałbym zaimplementować stronicowanie z tym.

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

Czego ja chcę

Mam posty na forum z powiązanymi wpisami. Chcę otrzymywać posty z ostatnio dodanymi wpisami, aby móc wybrać ostatnio omawiane posty.

Teraz chcę mieć możliwość uzyskania „10 do 20 ostatnio aktywnych postów” zamiast „10 najlepszych”.

Czego próbowałem

Próbowałem zaimplementować funkcje WIERSZ, tak jak w artykule, ale tak naprawdę bez powodzenia.

Jakieś pomysły, jak to wdrożyć?

Lars Holdgaard
źródło

Odpowiedzi:

288

W SQL Server 2012 jest to bardzo proste

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

Jeśli chcemy pominąć ORDER BY, możemy skorzystać z

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

(Wolałbym oznaczyć to jako hack - ale jest używane np. Przez NHibernate. Aby użyć mądrze dobranej kolumny, ponieważ preferowany jest sposób ORDER BY)

odpowiedzieć na pytanie:

--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

Wprowadzono nowe słowa kluczowe offseti fetch next(zgodnie ze standardami SQL).

Ale myślę, że nie używasz SQL Server 2012 , prawda ? W poprzedniej wersji jest to trochę (trochę) trudne. Oto porównanie i przykłady dla wszystkich wersji serwera SQL: tutaj

To może zadziałać w 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
Radim Köhler
źródło
Wielkie dzięki! To naprawdę dobra odpowiedź! Tylko pytanie o sql 2008. Chcę, aby KOLEJNOŚĆ nastąpiła przed GDZIE, ponieważ obecnie posortuje podzbiór, ale chcemy wybrać coś z całego zestawu ... Jakieś pomysły? :) Jeszcze raz dziękuję
Lars Holdgaard
2
Jeśli dobrze cię rozumiem, chcesz posortować według LastDate, prawda? wtedy możemy zmienić klauzulę OVER () w ten sposób: ROW_NUMBER () OVER (ORDER BY MAX (Datemade) desc ). I usuń ostatnie ORDER BY PostId . Teraz CTE powinno być sortowane „wcześniej” w razie potrzeby. poprawny?
Radim Köhler
1
Dziękuję, że pomogło, uwaga na temat próbki z 2012 r., Zamówienie według jest obowiązkowe, próbowałem tego bez klauzuli order by i otrzymałem błąd „nieprawidłowa składnia” Nie miałem pojęcia, co jest nie tak, dopóki nie sprawdzę składni MSDN i nie dowiedziałem się, że kolejność według jest obowiązkowa .
Esen
Czy pierwszy wiersz jest 1 czy 0? Czy GDZIE ma WHERE RowNumber >= @Start AND RowNumber < @Endotrzymać pierwsze 1000 wierszy, jeśli @Startwynosi 0 i @End1000?
CWSpear
1
Dziękuję bardzo
Mafii
8

Aby to zrobić w SQL Server, musisz uporządkować zapytanie według kolumny, aby móc określić żądane wiersze.

Przykład:

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

Nie możesz w tym celu używać słowa kluczowego „TOP”.

Możesz dowiedzieć się więcej tutaj: https://technet.microsoft.com/pt-br/library/gg699618%28v=sql.110%29.aspx

Felipe VR
źródło
5
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

użyj tego na końcu wybranej składni. =)

Nicolas Vinícius Sroczynski
źródło
5

SQL 2008

Odpowiedź Radima Köhlera działa, ale tutaj jest krótsza wersja:

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

Źródło: https://forums.asp.net/post/4033909.aspx

Tadej
źródło
-1

Możesz użyć zagnieżdżonego zapytania do paginacji w następujący sposób:

Paging od 4 Row do 8 Row, gdzie CustomerId jest kluczem podstawowym .

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
źródło