Implémenter la fonctionnalité de pagination (sauter / prendre) avec cette requête

138

J'ai essayé de comprendre un peu comment implémenter la pagination personnalisée dans SQL, par exemple en lisant des articles comme celui-ci .

J'ai la requête suivante, qui fonctionne parfaitement. Mais je voudrais implémenter la pagination avec celui-ci.

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

Qu'est-ce que je veux

J'ai des messages sur le forum, avec des entrées connexes. Je veux obtenir les messages avec les dernières entrées ajoutées, afin de pouvoir sélectionner les messages récemment débattus.

Maintenant, je veux pouvoir obtenir le "top 10 à 20 articles récemment actifs", au lieu du "top 10".

Qu'ai-je essayé

J'ai essayé d'implémenter les fonctions ROW comme celle de l'article, mais vraiment sans succès.

Des idées comment le mettre en œuvre?

Lars Holdgaard
la source

Réponses:

288

Dans SQL Server 2012, c'est très très simple

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

Si nous voulons sauter ORDER BY, nous pouvons utiliser

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

(Je préfère marquer cela comme un hack - mais il est utilisé, par exemple par NHibernate. Utiliser une colonne judicieusement choisie comme ORDER BY est la méthode préférée)

pour répondre à la question:

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

De nouveaux mots clés offsetet fetch next(juste en suivant les normes SQL) ont été introduits.

Mais je suppose que vous n'utilisez pas SQL Server 2012 , non ? Dans la version précédente, c'est un peu (un peu) difficile. Voici une comparaison et des exemples pour toutes les versions de serveur SQL: ici

Donc, cela pourrait fonctionner dans 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
la source
Merci beaucoup! C'est une très bonne réponse! Seule question sur le sql 2008. Je veux que ORDER BY se produise avant le WHERE, car il triera actuellement le sous-ensemble, mais nous voulons sélectionner quelque chose dans l'ensemble ... Des idées? :) Encore une fois, merci
Lars Holdgaard
2
Si je vous comprends bien, vous aimeriez trier par LastDate, non? alors nous pouvons changer la clause OVER () de cette façon: ROW_NUMBER () OVER (ORDER BY MAX (Datemade) desc ). Et supprimez le dernier ORDER BY PostId . Maintenant, le CTE devrait être trié «plus tôt» selon les besoins. correct?
Radim Köhler
1
Merci pour cette aide, une note sur l'échantillon 2012, commander par est obligatoire, j'essayais ceci sans ordre par clause et j'ai eu l'erreur "syntaxe incorrecte" je n'avais aucune idée de ce qui n'allait pas jusqu'à ce que je regarde dans la syntaxe MSDN et que j'apprenne que la commande par est obligatoire .
Esen
La première ligne est-elle 1 ou 0? Le WHERE devrait-il être WHERE RowNumber >= @Start AND RowNumber < @Endpour obtenir les 1000 premières lignes si @Startest 0 et @End1000?
CWSpear
1
Merci beaucoup
Mafii
8

Pour ce faire dans SQL Server, vous devez classer la requête par colonne afin de pouvoir spécifier les lignes souhaitées.

Exemple:

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

Et vous ne pouvez pas utiliser le mot-clé "TOP" lors de cette opération.

Vous pouvez en savoir plus ici: https://technet.microsoft.com/pt-br/library/gg699618%28v=sql.110%29.aspx

Felipe VR
la source
5
OFFSET     10 ROWS       -- skip 10 rows
FETCH NEXT 10 ROWS ONLY; -- take 10 rows

utilisez ceci à la fin de votre syntaxe de sélection. =)

Nicolas Vinícius Sroczynski
la source
5

SQL 2008

La réponse de Radim Köhler fonctionne, mais voici une version plus courte:

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

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

Tadej
la source
-1

Vous pouvez utiliser une requête imbriquée pour la pagination comme suit:

Pagination de 4 lignes à 8 lignes où CustomerId est la clé primaire .

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