Existe-t-il un moyen de faire en sorte qu'une Oracle
requête se comporte comme si elle contenait une MySQL limit
clause?
Dans MySQL
, je peux le faire:
select *
from sometable
order by name
limit 20,10
pour obtenir le 21e au 30e rangs (sauter les 20 premiers, donner les 10 suivants). Les lignes sont sélectionnées après le order by
, donc ça commence vraiment par le 20ème nom par ordre alphabétique.
Dans Oracle
, la seule chose que les gens mentionnent est la rownum
pseudo-colonne, mais elle est évaluée avant order by
, ce qui signifie ceci:
select *
from sometable
where rownum <= 10
order by name
renverra un ensemble aléatoire de dix lignes ordonnées par nom, ce qui n'est généralement pas ce que je veux. Il ne permet pas non plus de spécifier un décalage.
sql
oracle
pagination
sql-limit
Mathieu Longtin
la source
la source
ORDER BY
. C'est tout l'intérêt de commander en premier. Si les données sous-jacentes changent et que votre jeu de résultats change à cause de cela, alors pourquoi ne pas montrer à l'utilisateur les résultats mis à jour au lieu d'informations obsolètes? De plus, la gestion de l'État est un fléau à éviter autant que possible. C'est une source constante de complications et de bugs; c'est pourquoi la fonctionnalité devient si populaire. Et quand sauriez-vous expirer la totalité du jeu de résultats en mémoire? Sur le Web, vous n'avez aucun moyen de savoir quand l'utilisateur quitte.Réponses:
À partir d'Oracle 12c R1 (12.1), il existe une clause de limitation de ligne . Il n'utilise pas de
LIMIT
syntaxe familière , mais il peut mieux faire le travail avec plus d'options. Vous pouvez trouver la syntaxe complète ici . (Lisez également la façon dont cela fonctionne en interne dans Oracle dans cette réponse ).Pour répondre à la question d'origine, voici la requête:
(Pour les versions antérieures d'Oracle, veuillez vous référer aux autres réponses dans cette question)
Exemples:
Les exemples suivants ont été cités à partir de la page liée , dans l'espoir d'empêcher la pourriture des liens.
Installer
Qu'y a-t-il dans le tableau?
Obtenez les premières
N
lignesObtenez les premières
N
lignes, siN
la ligne a des liens, obtenez toutes les lignes liéesTop
x
% des lignesUtiliser un offset, très utile pour la pagination
Vous pouvez combiner l'offset avec des pourcentages
la source
OFFSET FETCH
syntaxe est un sucre de syntaxe. DétailsVous pouvez utiliser une sous-requête pour cela comme
Consultez également la rubrique Sur ROWNUM et la limitation des résultats chez Oracle / AskTom pour plus d'informations.
Mise à jour : pour limiter le résultat avec les limites inférieures et supérieures, les choses deviennent un peu plus gonflées avec
(Copié à partir de l'article AskTom spécifié)
Mise à jour 2 : à partir d'Oracle 12c (12.1), une syntaxe est disponible pour limiter les lignes ou démarrer à des décalages.
Voir cette réponse pour plus d'exemples. Merci à Krumia pour l'astuce.
la source
J'ai fait des tests de performances pour les approches suivantes:
Asktom
Analytique
Alternative courte
Résultats
La table comptait 10 millions d'enregistrements, le tri se faisait sur une ligne datetime non indexée:
La sélection des 10 premières lignes a pris:
Sélection de lignes entre 100 000 et 100 010:
Sélection de lignes entre 9 000 000 et 9 000 010:
la source
BETWEEN
n'est qu'un raccourci pour>= AND <=
( stackoverflow.com/questions/4809083/between-clause-versus-and )offset
syntaxe a le même plan et les mêmes performances que l'approche analytique.Une solution analytique avec une seule requête imbriquée:
Rank()
peut être remplacéRow_Number()
mais peut renvoyer plus d'enregistrements que vous ne le pensez s'il existe des valeurs en double pour le nom.la source
rank()
il convient également de noterdense_rank()
ce qui peut être plus utile pour le contrôle de la sortie car ce dernier ne "saute" pas les chiffres, alors qu'il lerank()
peut. Dans tous les cas, cette questionrow_number()
est la mieux adaptée. Un autre n'est pas cette technique est applicable à toute base de données qui prend en charge les fonctions mentionnées.Sur Oracle 12c (voir la clause de limitation de ligne dans la référence SQL ):
la source
LIMIT
SQL: 2008, ils ont ensuite dû retirer une feuille du livre de Microsoft et briser la norme.LIMIT ... OFFSET
LIMIT n, m
(voir ma réponse). Là encore, Oracle aurait dû implémenterLIMIT n, m
comme sucre syntaxique, car il est équivalent àOFFSET n ROWS FETCH NEXT m ROWS ONLY
.Les requêtes de pagination avec ordre sont vraiment délicates dans Oracle.
Oracle fournit une pseudocolonne ROWNUM qui renvoie un nombre indiquant l'ordre dans lequel la base de données sélectionne la ligne dans une table ou un ensemble de vues jointes.
ROWNUM est une pseudocolonne qui cause des problèmes à de nombreuses personnes. Une valeur ROWNUM n'est pas affectée en permanence à une ligne (il s'agit d'un malentendu courant). Il peut être déroutant lorsqu'une valeur ROWNUM est réellement affectée. Une valeur ROWNUM est affectée à une ligne après avoir transmis les prédicats de filtre de la requête mais avant l'agrégation ou le tri de la requête .
De plus, une valeur ROWNUM n'est incrémentée qu'après avoir été affectée.
C'est pourquoi la requête de suivi ne renvoie aucune ligne:
La première ligne du résultat de la requête ne transmet pas le prédicat ROWNUM> 1, donc ROWNUM n'incrémente pas à 2. Pour cette raison, aucune valeur ROWNUM n'est supérieure à 1, par conséquent, la requête ne renvoie aucune ligne.
Une requête correctement définie doit ressembler à ceci:
En savoir plus sur les requêtes de pagination dans mes articles sur le blog Vertabelo :
la source
SQL Standard
Comme je l'ai expliqué dans cet article , la norme SQL: 2008 fournit la syntaxe suivante pour limiter l'ensemble de résultats SQL:
Oracle 11g et versions antérieures
Avant la version 12c, pour récupérer les enregistrements Top-N, vous deviez utiliser une table dérivée et la pseudocolonne ROWNUM:
la source
Moins d'instructions SELECT. En outre, moins consommatrice de performances. Crédits à: [email protected]
la source
En tant qu'extension de la réponse acceptée, Oracle utilise en interne des
ROW_NUMBER/RANK
fonctions.OFFSET FETCH
la syntaxe est un sucre de syntaxe.Il pourrait être observé en utilisant la
DBMS_UTILITY.EXPAND_SQL_TEXT
procédure:Préparation de l'échantillon:
Requete:
est régulier:
démo db <> violon
Récupération du texte SQL développé:
WITH TIES
est étendu commeRANK
:et offset:
la source
Si vous n'êtes pas sur Oracle 12C, vous pouvez utiliser la requête TOP N comme ci-dessous.
Vous pouvez même déplacer ceci de la clause avec la clause comme suit
Ici, en fait, nous créons une vue en ligne et renommons rownum en rnum. Vous pouvez utiliser rnum dans la requête principale comme critère de filtre.
la source
ORDER BY
et lerownum
séparément. Fondamentalement, j'ai créé une sous-requête contenant laORDER BY
clause .rownum
devrait donc être en dehors d'une sous-requête.J'ai commencé à me préparer pour l'examen Oracle 1z0-047, validé contre 12c. En me préparant, je suis tombé sur une amélioration 12c connue sous le nom de `` FETCH FIRST ''. Elle vous permet de récupérer des lignes / limiter les lignes selon votre convenance. Plusieurs options sont disponibles avec elle
Exemple:
la source
plus les valeurs découvrent
moins que les valeurs découvrent
la source
ROW_NUMBER()
solution basée avait déjà été publié par Leigh Riffel. Dans la dépendance, il y a des erreurs de syntaxe dans le code affiché.Pour chaque ligne renvoyée par une requête, la pseudocolonne ROWNUM renvoie un nombre indiquant l'ordre dans lequel Oracle sélectionne la ligne dans une table ou un ensemble de lignes jointes. La première ligne sélectionnée a un ROWNUM de 1, la seconde en a 2, etc.
Je l'ai implémenté dans le
oracle
serveur11.2.0.1.0
la source
Dans le cas de SQL-Developer, il ne récupère automatiquement que les 50 premières lignes. Et si nous faisons défiler vers le bas, il récupère encore 50 lignes et ainsi de suite!
Par conséquent, nous n'avons pas besoin de définir, en cas d'outil sql-developer!
la source
Dans l'oracle
VAL
5 lignes sélectionnées.
SQL>
la source
(non testé) quelque chose comme ça peut faire le travail
Il y a aussi le classement de la fonction analytique, que vous pouvez utiliser pour classer.
la source
Comme ci-dessus avec des corrections. Fonctionne mais certainement pas joli.
Honnêtement, il vaut mieux utiliser les réponses ci-dessus.
la source