Come posso limitare il numero di righe restituite da una query Oracle dopo l'ordine?

C'è un modo per far sì che una query Oracle si comporti come se contenesse una clausola MySQL limit?

In MySQL, posso fare questo:

select * 
from sometable
order by name
limit 20,10

per ottenere le righe dalla 21esima alla 30esima (saltare le prime 20, dare le successive 10). Le righe sono selezionate dopo il order by, quindi inizia davvero dal 20° nome in ordine alfabetico.

In Oracle, l'unica cosa che la gente menziona è la pseudo-colonna rownum, ma viene valutata prima di order by, il che significa questo:

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

restituirà un insieme casuale di dieci righe ordinate per nome, che di solito non è quello che voglio. Inoltre non permette di specificare un offset.

Puoi usare una subquery per questo come


select *
from  
( select * 
  from emp 
  order by sal desc ) 
where ROWNUM 
Commentari (6)

Una soluzione analitica con una sola query annidata:

SELECT * FROM
(
   SELECT t.*, Row_Number() OVER (ORDER BY name) MyRow FROM sometable t
) 
WHERE MyRow BETWEEN 10 AND 20;

Rank() potrebbe essere sostituito da Row_Number() ma potrebbe restituire più record di quanto ci si aspetta se ci sono valori duplicati per il nome.

Commentari (3)

(non testato) qualcosa come questo potrebbe fare il lavoro

WITH
base AS
(
    select *                   -- get the table
    from sometable
    order by name              -- in the desired order
),
twenty AS
(
    select *                   -- get the first 30 rows
    from base
    where rownum < 30
    order by name              -- in the desired order
)
select *                       -- then get rows 21 .. 30
from twenty
where rownum > 20
order by name                  -- in the desired order

C'è anche la funzione analitica rank, che potete usare per ordinare per.

Commentari (2)