Najlepszym sposobem na to jest użycie funkcji analitycznych, RANK() lub 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() kompresuje luki w przypadku remisu:
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>
Preferowane zachowanie zależy od wymagań biznesowych.
Istnieje również funkcja analityczna ROW_NUMBER(), której możemy użyć do zwrócenia dokładnej liczby wierszy. Powinniśmy jednak unikać korzystania z rozwiązań opartych na numerze wierszy, chyba że logika biznesowa chętnie arbitralnie skróci zbiór wyników w przypadku remisu. Istnieje różnica między pytaniem o pięć najwyższych wartości oraz pierwsze pięć rekordów posortowanych według wysokich wartości
Istnieje również rozwiązanie nieanalityczne wykorzystujące pseudokolumnę ROWNUM. Jest to niezgrabne, ponieważ ROWNUM jest stosowane przed klauzulą ORDER BY, co może prowadzić do nieoczekiwanych wyników. Rzadko istnieje powód, aby używać ROWNUM zamiast ROW_NUMBER() lub jednej z funkcji rankingowych.