Il modo migliore per farlo è con le funzioni analitiche, RANK() o DENSE_RANK() ...
SQL> select * from (
2 select empno
3 , sal
4 , rank() over (order by sal desc) as rnk
5 from emp)
6 where rnk <= 5
7 /
EMPNO SAL RNK
---------- ---------- ----------
7839 5000 1
7788 3000 2
7902 3000 2
7566 2975 4
8083 2850 5
7698 2850 5
6 rows selected.
SQL>
DENSE_RANK() comprime gli spazi vuoti quando c'è un pareggio:
SQL> select * from (
2 select empno
3 , sal
4 , dense_rank() over (order by sal desc) as rnk
5 from emp)
6 where rnk <= 5
7 /
EMPNO SAL RNK
---------- ---------- ----------
7839 5000 1
7788 3000 2
7902 3000 2
7566 2975 3
8083 2850 4
7698 2850 4
8070 2500 5
7 rows selected.
SQL>
Il comportamento che preferisci dipende dalle tue esigenze aziendali.
C'è anche la funzione analitica ROW_NUMBER() che possiamo usare per restituire un numero preciso di righe. Tuttavia, dovremmo evitare di utilizzare soluzioni basate sul numero di riga a meno che la logica aziendale non sia felice di troncare arbitrariamente il set di risultati in caso di pareggio. C'è differenza tra chiedere i cinque valori più alti e i primi cinque record ordinati per valori elevati
Esiste anche una soluzione non analitica che utilizza la pseudo-colonna ROWNUM. Questo è goffo perché ROWNUM viene applicato prima della clausola ORDER BY, che può portare a risultati imprevisti. Raramente c'è un motivo per usare ROWNUM invece di ROW_NUMBER() o una delle funzioni di ranking.