2009-03-03 12 views

Répondre

8

La plupart des gens vous diront couramment d'utiliser ROWNUM, pour ce faire, mais la façon la plus succincte est d'utiliser la fonction analytique row_number().

select EMPLID, EFFDT, ACTION, ACTION_REASON 
from 
(
SELECT EMPLID, EFFDT, ACTION, ACTION_REASON, row_number() over (order by emplid) rn 
from JOB where emplid ='12345' 
) 
where rn between 50 and 60; 

Utilisation de la fonction row_number vous permet de commander les résultats et les numéroter dans une seule requête, vous avez juste besoin d'une requête d'emballage pour obtenir les lignes dont vous avez besoin.

+0

Merci Nick, ça a marché. J'apprécie vraiment votre aide. –

+0

Pas vrai: juste parce qu'il ressemble à une requête dans une requête dans une requête, cela ne signifie pas qu'Oracle l'implémente comme ça. J'ai juste testé chaque méthode 10 000 fois et ils ont fonctionné en 69 et 78 ms (le vôtre était le plus lent, mais la différence est insignifiante). Expliquer Le plan montre ce qui se passe –

+0

Sur mon système, les temps sont insignifiants dans la plage de 1,5 ms de ma table, mais la syntaxe de row_number est plus propre et ne nécessite pas deux vues en ligne. Voir Tom Kyte, http://www.oracle.com/technology/oramag/oracle/07-jan/o17asktom.html – Nick

7

Il est un peu délicat dans Oracle, je pense que vous devez faire quelque chose comme ceci:

SELECT EMPLID,EFFDT,ACTION,ACTION_REASON 
FROM (SELECT ROWNUM rnum, EMPLID,EFFDT,ACTION,ACTION_REASON 
     FROM (SELECT EMPLID,EFFDT,ACTION,ACTION_REASON 
      FROM JOB 
      WHERE emplid = '12345') 
     WHERE rownum <= 60 
) 
WHERE rnum >= 50; 
+0

Est-ce que ORDER BY est sensible? – Tomalak

+0

Non, il est calculé uniquement lorsque la ligne est déjà récupérée. – Quassnoi

+0

Je crois si http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/pseudocolumns009.htm#SQLRF00255 –

0

Vous pouvez utiliser ROWNUM (voir this link). Si vous devez contrôler l'ordre de tri, vous pouvez envelopper une autre requête autour de votre requête.

+0

Je vous remercie tous pour votre réponse rapide. J'apprécie vraiment votre aide. –

8

Depuis que j'ai fait une comparaison de Chad's et Nick's approches pour faire un commentaire sur la réponse de Nick, je pensais que je posterais mes résultats ici. Je paquet de Tom Kyte runstats pour les comparer avec ce script:

begin 
    runstats_pkg.rs_start('Chad'); 
    for i in 1..10000 loop 
    for r in (
     SELECT EMPLID,EFFDT,ACTION,ACTION_REASON 
     FROM (SELECT ROWNUM rnum, EMPLID,EFFDT,ACTION,ACTION_REASON 
      FROM (SELECT EMPLID,EFFDT,ACTION,ACTION_REASON 
        FROM JOB 
        WHERE emplid = '12345') 
      WHERE rownum <= 60 
    ) 
     WHERE rnum >= 50 
    ) loop 
     null; 
     end loop; 
    end loop; 
    runstats_pkg.rs_middle('Nick'); 
    for i in 1..10000 loop 
    for r in (
     select EMPLID, EFFDT, ACTION, ACTION_REASON 
     from 
     (
     SELECT EMPLID, EFFDT, ACTION, ACTION_REASON, row_number() over (order by emplid) rn 
     from JOB where emplid ='12345' 
    ) 
     where rn between 50 and 60 
    ) loop 
     null; 
     end loop; 
    end loop; 
    runstats_pkg.rs_stop(0,false,false,false,false,false,false,false,false); 
end; 
/

Les résultats:

Run1 = Chad 
Run2 = Nick 

*** Comparative Time Report *** 
Run         Time (hsecs) 
-------------------------------------------------- 
Run1           69 
Run2           77 

Run1 ran in 89.61% of the time of Run2 
Run2 ran in 111.59% of the time of Run1 

PL/SQL procedure successfully completed. 

Utilisation autotrace les plans peuvent être vu être assez similaire:

SQL>   SELECT EMPLID,EFFDT,ACTION,ACTION_REASON 
    2   FROM (SELECT ROWNUM rnum, EMPLID,EFFDT,ACTION,ACTION_REASON 
    3     FROM (SELECT EMPLID,EFFDT,ACTION,ACTION_REASON 
    4      FROM JOB 
    5      WHERE emplid = '12345') 
    6     WHERE rownum <= 60 
    7   ) 
    8   WHERE rnum >= 50 
    9/

no rows selected 


Execution Plan 
---------------------------------------------------------- 

------------------------------------------------------------------------------ 
| Id | Operation      | Name | Rows | Bytes | Cost (%CPU)| 
------------------------------------------------------------------------------ 
| 0 | SELECT STATEMENT    |   |  1 | 41 |  3 (0)| 
|* 1 | VIEW       |   |  1 | 41 |  3 (0)| 
|* 2 | COUNT STOPKEY    |   |  |  |   | 
| 3 | TABLE ACCESS BY INDEX ROWID| JOB  |  1 | 13 |  3 (0)| 
|* 4 |  INDEX RANGE SCAN   | JOB2_PK |  1 |  |  2 (0)| 
------------------------------------------------------------------------------ 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - filter("RNUM">=50) 
    2 - filter(ROWNUM<=60) 
    4 - access("EMPLID"=12345) 


Statistics 
---------------------------------------------------------- 
      1 recursive calls 
      0 db block gets 
      2 consistent gets 
      0 physical reads 
      0 redo size 
     264 bytes sent via SQL*Net to client 
     231 bytes received via SQL*Net from client 
      1 SQL*Net roundtrips to/from client 
      0 sorts (memory) 
      0 sorts (disk) 
      0 rows processed 

SQL>   select EMPLID, EFFDT, ACTION, ACTION_REASON 
    2   from 
    3   (
    4   SELECT EMPLID, EFFDT, ACTION, ACTION_REASON, row_number() over (order by emplid) rn 
    5   from JOB where emplid ='12345' 
    6   ) 
    7   where rn between 50 and 60 
    8/

no rows selected 


Execution Plan 
---------------------------------------------------------- 

------------------------------------------------------------------------------ 
| Id | Operation      | Name | Rows | Bytes | Cost (%CPU)| 
------------------------------------------------------------------------------ 
| 0 | SELECT STATEMENT    |   |  1 | 41 |  3 (0)| 
|* 1 | VIEW       |   |  1 | 41 |  3 (0)| 
|* 2 | WINDOW NOSORT STOPKEY  |   |  1 | 17 |  3 (0)| 
| 3 | TABLE ACCESS BY INDEX ROWID| JOB  |  1 | 17 |  3 (0)| 
|* 4 |  INDEX RANGE SCAN   | JOB2_PK |  1 |  |  2 (0)| 
------------------------------------------------------------------------------ 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - filter("RN">=50 AND "RN"<=60) 
    2 - filter(ROW_NUMBER() OVER (ORDER BY "EMPLID")<=60) 
    4 - access("EMPLID"=12345) 
     filter("EMPLID"=12345) 


Statistics 
---------------------------------------------------------- 
      1 recursive calls 
      0 db block gets 
      2 consistent gets 
      0 physical reads 
      0 redo size 
     264 bytes sent via SQL*Net to client 
     231 bytes received via SQL*Net from client 
      1 SQL*Net roundtrips to/from client 
      0 sorts (memory) 
      0 sorts (disk) 
      0 rows processed 

Il Il semblerait qu'il n'y ait pas beaucoup à choisir entre les 2 méthodes, bien que le Tchad soit toujours légèrement plus rapide sur ma base de données qui est:

Oracle Database 10g version 10.2.0.3.0 - 64bit Production

+0

Hm. Si ce n'est pas au-dessus et au-delà, alors je ne sais pas ce que c'est. ;-) +1 – Tomalak

+0

Oui, c'est un triste acte d'accusation de mon après-midi! –

Questions connexes