2 votes

Pagination en SQL sans rupture sur la clé primaire

Je suis nouveau sur Stackoverflow. Veuillez me pardonner si j'ai commis une erreur.

J'ai les données suivantes en SQL.

Nº de ligne Client Nº     Nom du client
------------------------------------------------------------
1        1234          ABCD
2        1234          ABCD
3        1234          ABCD
4        6789          WXYZ
5        6789          WXYZ
6        3456          OPQR
7        4567          JKLM

J'ai besoin de paginer les données ci-dessus avec la contrainte suivante

  • Taille de page : 4 enregistrements
  • Si le numéro du client est réparti entre deux pages, le nouveau numéro de client doit aller sur la page suivante.

Sortie souhaitée:

Pagination avec 4 enregistrements par page

1ère Page

Nº de ligne Client Nº     Nom du client
------------------------------------------------------------
1        1234          ABCD
2        1234          ABCD
3        1234          ABCD

2ème Page

Nº de ligne Client Nº     Nom du client
------------------------------------------------------------
4        6789          WXYZ
5        6789          WXYZ
6        3456          OPQR
7        4567          JKLM

Veuillez m'aider.

0voto

StanislavL Points 31343

Vous pouvez lire la taille de page +1 enregistrements en utilisant une limitation, puis si le dernier enregistrement et l'avant-dernier ont le même nom de client, filtrez simplement le client en utilisant HAVING.

Cela pourrait être délicat et dépend de la base de données que vous utilisez et pourrait être facilement réalisé sur la couche de présentation

0voto

Déclarez @PageNumber INT = 1,  @PageSize   INT = 4
;with cte1(RowNo,CustomerNo,CustomerName)
AS
(
Select 1,1234,'ABCD' union all
Select 2,1234,'ABCD' union all
Select 3,1234,'ABCD' union all
Select 4,6789,'WXYZ' union all
Select 5,6789,'WXYZ' union all
Select 6,3456,'OPQR' union all
Select 7,4567,'JKLM' 
)
select * from cte1 order by RowNo
 OFFSET @PageSize * (@PageNumber - 1) ROWS
      FETCH NEXT @PageSize ROWS ONLY

0voto

Nenad Zivkovic Points 14392

Cela peut être fait et pas trop compliqué en utilisant une CTE récursive.

Pour les données d'exemple, j'ai utilisé la requête d'une autre réponse

WITH cte1(RowNo,CustomerNo,CustomerName)
AS
(
    SELECT 1,1234,'ABCD' UNION ALL
    SELECT 2,1234,'ABCD' UNION ALL
    SELECT 3,1234,'ABCD' UNION ALL
    SELECT 4,6789,'WXYZ' UNION ALL
    SELECT 5,6789,'WXYZ' UNION ALL
    SELECT 6,3456,'OPQR' UNION ALL
    SELECT 7,4567,'JKLM' 
)
SELECT * INTO #table FROM cte1

Je vais ajouter une autre ligne avec un utilisateur réapparaissant pour diviser cela en 3ème page

INSERT #table (RowNo, CustomerNo, CustomerName) VALUES (8,3456,'OPQR')

Et voici la solution. J'ai ajouté des commentaires pour expliquer les parties

WITH CTE_Source AS 
(
    --J'utilise ceci pour ajouter la colonne RN simplement car je ne peux pas garantir qu'il n'y aura pas de lacunes dans la colonne RowNo
    SELECT *
    , ROW_NUMBER() OVER (ORDER BY RowNo) RN 
    FROM #table t
)
, CTE_R AS 
(
    --La première partie est la sélection de la première ligne
    SELECT s.RowNo
         , s.CustomerNo
         , s.CustomerName
         , s.RN
         , 1 AS Grp --c'est un groupe actuel de lignes
         , 1 AS Cnt --compteur du nombre de lignes dans le groupe
    FROM CTE_Source s WHERE RN = 1
    UNION ALL
    --La sélection ultérieure est pour la ligne suivante
    SELECT 
         s.RowNo
         , s.CustomerNo
         , s.CustomerName
         , s.RN 
         --augmenter le groupe lorsqu'il y a un client différent
         , CASE WHEN s.CustomerNo = r.CustomerNo THEN r.Grp ELSE r.Grp+Cnt END
         --augmenter le compteur lorsqu'il y a le même client
         , CASE WHEN s.CustomerNo = r.CustomerNo THEN r.Cnt + 1 ELSE 1 END
    FROM CTE_R r
    INNER JOIN CTE_Source s ON s.RN = r.Rn + 1

)
, CTE_Paging AS 
(
    SELECT *
    , CEILING((r.Grp + r.Cnt) / 4.) AS Page -- remplacez 4 par la taille de votre page
    FROM CTE_R r
)
SELECT * FROM CTE_Paging --Ajoutez simplement WHERE Page = si vous voulez une page spécifique
OPTION (MAXRECURSION 0) -- pour une récursion illimitée si vous avez plus de 100 lignes

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X