Implementare la funzionalità di paging (skip / take) con questa query


138

Ho cercato di capire un po 'come implementare il paging personalizzato in SQL, ad esempio leggendo articoli come questo .

Ho la seguente domanda, che funziona perfettamente. Ma vorrei implementare il paging con questo.

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

Cosa voglio?

Ho post sul forum, con voci correlate. Voglio ottenere i post con le ultime voci aggiunte, quindi posso selezionare i post recentemente discussi.

Ora, voglio essere in grado di ottenere i "primi 10-20 post attivi di recente", anziché "i primi 10".

Cosa ho provato

Ho cercato di implementare le funzioni ROW come quella nell'articolo, ma davvero senza fortuna.

Qualche idea su come implementarlo?

Risposte:


288

In SQL Server 2012 è molto semplice

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

Se vogliamo saltare ORDER BY, possiamo usare

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

(Preferirei contrassegnarlo come un hack - ma è usato, ad esempio da NHibernate. Usare una colonna saggiamente raccolta come ORDER BY è il modo preferito)

per rispondere alla domanda:

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

Sono state introdotte nuove parole chiave offsete fetch next(solo seguendo gli standard SQL).

Ma suppongo che non stai usando SQL Server 2012 , giusto ? Nella versione precedente è un po '(un po') difficile. Ecco un confronto ed esempi per tutte le versioni di SQL Server: qui

Quindi, questo potrebbe funzionare in 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

Molte grazie! Questa è davvero una buona risposta! Unica domanda su quello del 2008. Voglio che ORDER BY accada prima di WHERE, poiché attualmente ordinerà il sottoinsieme, ma vogliamo selezionare qualcosa dall'intero set ... Qualche idea? :) Ancora una volta, grazie
Lars Holdgaard il

2
Se ti capisco correttamente, ti piacerebbe ordinare per LastDate, giusto? quindi possiamo modificare la clausola OVER () in questo modo: ROW_NUMBER () OVER (ORDER BY MAX (Datemade) desc ). E rimuovi l'ultimo ORDER BY PostId . Ora il CTE dovrebbe essere ordinato "prima" secondo necessità. corretta?
Radim Köhler,

1
Grazie, questo mi ha aiutato, una nota sull'esempio del 2012, ordina per è obbligatorio, stavo provando questo senza ordine per clausola e ho ricevuto l'errore "sintassi errata" non avevo idea di cosa fosse sbagliato fino a quando non ho esaminato la sintassi MSDN e ho imparato che l'ordine è obbligatorio .
Esen,

La prima riga è 1 o 0? Dovrebbe essere il DOVE WHERE RowNumber >= @Start AND RowNumber < @Endottenere le prime 1000 righe se @Startè 0 ed @Endè 1000?
CWSpear

1
Grazie mille
Mafii,



5

SQL 2008

La risposta di Radim Köhler funziona, ma ecco una versione più breve:

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

Fonte: https://forums.asp.net/post/4033909.aspx


-1

È possibile utilizzare la query nidificata per l'impaginazione come segue:

Paging da 4 righe a 8 righe in cui CustomerId è la chiave primaria .

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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.