904 votes

Comment puis-je limiter le nombre de lignes renvoyées par une requête Oracle après la commande?

Est-il un moyen de faire une requête Oracle se comportera comme s'il contient une base de données MySQL limit clause?

Dans MySQL, je peux faire ceci:

select * 
from sometable
order by name
limit 20,10

pour obtenir la 21e à la 30e lignes (ignorer les 20 premiers, donnez la prochaine 10). Les lignes sont sélectionnées après l' order by, de sorte qu'il commence vraiment sur le 20e nom dans l'ordre alphabétique.

Dans Oracle, la seule chose que les gens parler, est l' rownum de la pseudo-colonne, mais il est évalué avant d' order by, ce qui signifie ceci:

select * 
from sometable
where rownum <= 10
order by name

sera de retour un ensemble aléatoire de dix lignes ordonnée par nom, ce qui n'est généralement pas ce que je veux. Il ne permet pas non plus pour la spécification d'un décalage.

747voto

Kosi2801 Points 9487

Vous pouvez utiliser une sous-requête pour cela comme

 select *
from  
( select * 
  from emp 
  order by sal desc ) 
where ROWNUM <= 5;
 

Jetez également un coup d'œil à la rubrique Sur ROWNUM et limitez les résultats à Oracle / AskTom pour plus d'informations.

Mise à jour : Pour limiter le résultat avec les limites inférieure et supérieure, les choses deviennent un peu plus gonflées avec

 select * from 
( select a.*, ROWNUM rnum from 
  ( <your_query_goes_here, with order by> ) a 
  where ROWNUM <= :MAX_ROW_TO_FETCH )
where rnum  >= :MIN_ROW_TO_FETCH;
 

(Copié à partir de l'article AskTom spécifié)

172voto

zeldi Points 2065

J'ai fait quelques tests de performances entre:

A.) Asktom

select * from (
  select a.*, ROWNUM rnum from (
    <select statemenet with order by clause>
  ) a where rownum <= MAX_ROW
) where rnum >= MIN_ROW

B.) approche Analytique

select * from (
  <select statemenet with order by clause>
) where myrow between MIN_ROW and MAX_ROW

C.) Court alternative

select * from (
  select statement, rownum as RN with order by clause
) where a.rn >= MIN_ROW and a.rn <= MAX_ROW

Résultats:

Table de 10 millions de dossiers, le tri a été sur un indexée datetime ligne:

  • Expliquer le plan a montré la même valeur pour tous les trois sélectionne (323168)
  • Mais le gagnant est AskTom (avec analytique, suivi de près derrière)

Sélection des 10 premières lignes a eu:

  • AskTom: 28 à 30 secondes
  • Analyse: de 33 à 37 secondes
  • Court alternative: 110 à 140 secondes

La sélection de lignes entre 100.000 et 100.010:

  • AskTom: 60 secondes
  • Analytique: 100 secondes

La sélection de lignes entre 9.000.000 et 9.000.010:

  • AskTom: 130 secondes
  • Analyse: 150 secondes

53voto

Leigh Riffel Points 2550
<p>Une solution analytique avec qu’une seule requête imbriquée :<pre><code></code></pre><p>Rank() pouvait remplacer Row_Number() mais peut retourner plus d’enregistrements que vous attendez si il y a des doublons de nom.</p></p>

28voto

beldaz Points 1432
<p>Sur Oracle 12C (voir ligne limitant la clause <a href="http://docs.oracle.com/cd/E16655_01/server.121/e17209/statements_10002.htm#SQLRF55631">SQL reference</a>) :<pre><code></code></pre></p>

6voto

Moins d'instructions SELECT. En outre, moins de performances consommatrices. Crédits à: anibal@upf.br

 SELECT *
    FROM   (SELECT t.*,
                   rownum AS rn
            FROM   shhospede t) a
    WHERE  a.rn >= in_first
    AND    a.rn <= in_first;
 

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: