Problème: j’ai besoin d’écrire des procédures stockées qui renverront le jeu de résultats d’une seule page de lignes et le nombre total de lignes.
Solution A: Je crée deux procédures stockées, une qui renvoie un ensemble de résultats d'une page et une autre qui renvoie un scalaire - nombre total de lignes. Le plan Explain indique que le premier sproc a un coût de 9 et le second 3.
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY D.ID DESC ) AS RowNum, ...
) AS PageResult
WHERE RowNum >= @from
AND RowNum < @to
ORDER BY RowNum
SELECT COUNT(*)
FROM ...
Solution B: J'ai tout mis dans un seul sproc en ajoutant le même numéro TotalRows
à la ligne toutes les du jeu de résultats. Cette solution a l'air malpropre, mais a un coût de 9 et un seul sproc, donc je suis enclin à utiliser cette solution.
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY D.ID DESC ) RowNum, COUNT(*) OVER () TotalRows,
WHERE RowNum >= from
AND RowNum < to
ORDER BY RowNum;
Existe-t-il une meilleure pratique de pagination dans Oracle? Laquelle des solutions susmentionnées est la plus utilisée dans la pratique? Est-ce que l'un d'entre eux est considéré comme tout simplement faux? Notez que ma base de données est et restera relativement petite (moins de 10 Go).
J'utilise Oracle 11g et le dernier fichier ODP.NET avec VS2010 SP1 et Entity Framework 4.4. J'ai besoin de la solution finale pour fonctionner au sein de l'EF 4.4. Je suis sûr qu'il existe probablement de meilleures méthodes pour la pagination en général, mais j'ai besoin qu'elles fonctionnent avec EF.
Si vous utilisez déjà l'analyse (ROW_NUMBER() OVER ...
), l'ajout d'une autre fonction analytique sur le même partitionnement entraînera un coût négligeable pour la requête.
Par ailleurs, il existe de nombreuses autres façons de faire la pagination, l’une d’elles utilisant rownum
:
SELECT *
FROM (SELECT A.*, rownum rn
FROM (SELECT *
FROM your_table
ORDER BY col) A
WHERE rownum <= :Y)
WHERE rn >= :X
Cette méthode sera supérieure si vous avez un index approprié sur la colonne de classement. Dans ce cas, il serait peut-être plus efficace d'utiliser deux requêtes (une pour le nombre total de lignes, une pour le résultat).
Les deux méthodes sont appropriées, mais en général, si vous souhaitez à la fois le nombre de lignes et un ensemble de pagination, l'utilisation de l'analyse est plus efficace, car vous interrogez les lignes une seule fois.
Cela peut aider:
SELECT * FROM
( SELECT deptno, ename, sal, ROW_NUMBER() OVER (ORDER BY ename) Row_Num FROM emp)
WHERE Row_Num BETWEEN 5 and 10;
Dans Oracle 12C, vous pouvez utiliser la limite LIMIT
et OFFSET
pour la pagination.
Exemple - Supposons que vous disposiez de la table tab
à partir de laquelle les données doivent être extraites sur la base de la colonne de type de données DATE
dt
dans l'ordre décroissant à l'aide de la pagination.
page_size:=5
select * from tab
order by dt desc
OFFSET nvl(page_no-1,1)*page_size ROWS FETCH NEXT page_size ROWS ONLY;
Explication:
page_no = 1 page_size = 5
OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY
- Récupère les 5 premières lignes uniquement
page_no = 2 page_size = 5
OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY
- Récupère les 5 prochaines lignes
etc.
Pages de référence -
https://Oracle-base.com/articles/12c/row-limiting-clause-for-top-n-queries-12cr1#paging
Essaye ça:
select * from ( select * from "table" order by "column" desc ) where ROWNUM > 0 and ROWNUM <= 5;
J'ai également fait face à un problème similaire. J'ai essayé toutes les solutions ci-dessus et aucune ne m'a donné de meilleures performances. J'ai un tableau avec des millions d'enregistrements et j'ai besoin de les afficher à l'écran en pages de 20. J'ai procédé comme suit pour résoudre le problème.
Cette méthode est efficace si nous devons effectuer une extraction de pagination inconditionnelle sur une table volumineuse.
Désolé, celui-ci fonctionne avec le tri:
SELECT * FROM (SELECT ROWNUM rnum,a.* FROM (SELECT * FROM "tabla" order by "column" asc) a) WHERE rnum BETWEEN "firstrange" AND "lastrange";