Най-добрият начин да направите това е с аналитични функции, RANK() или 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() компресира пропуските, когато има равенство:
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>
Кое поведение предпочитате зависи от вашите бизнес изисквания.
Съществува и аналитичната функция ROW_NUMBER(), която можем да използваме, за да върнем точен брой редове. Въпреки това, трябва да избягваме да използваме решения, базирани на номера на ред, освен ако бизнес логиката е щастлива да съкрати произволно набора от резултати в случай на равенство. Има разлика между това да поискате петте най-високи стойности и първите пет записа, сортирани по високи стойности
Има и неаналитично решение, използващо псевдоколона ROWNUM. Това е тромаво, защото ROWNUM се прилага преди клаузата ORDER BY, което може да доведе до неочаквани резултати. Рядко има причина да използвате ROWNUM вместо ROW_NUMBER() или някоя от функциите за класиране.