Oracle SQL - How to Retrieve highest 5 values of a column [duplicate]
How do you write a query where only a select number of rows are returned with either the highest or lowest column value.
i.e. A report with the 5 highest salaried employees?
Solution 1:
The best way to do this is with analytic functions, RANK() or 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() compresses the gaps when there is a tie:
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>
Which behaviour you prefer depends upon your business requirements.
There is also the ROW_NUMBER() analytic function which we can use to return a precise number of rows. However, we should avoid using solutions based on row number unless the business logic is happy to arbitrarily truncate the result set in the event of a tie. There is a difference between asking for the five highest values and the first five records sorted by high values
There is also a non-analytic solution using the ROWNUM pseudo-column. This is clunky because ROWNUM is applied before the ORDER BY clause, which can lead to unexpected results. There is rarely any reason to use ROWNUM instead of ROW_NUMBER() or one of the ranking functions.
Solution 2:
Try this one:
SELECT * FROM
(SELECT field1, field2 FROM fields order by field1 desc)
where rownum <= 5
Also take a look on this resource for a more detailed description on how rownum works.
Solution 3:
Oracle 9i+ provides analytic functions:
- ROW_NUMBER
- RANK
- DENSE_RANK
All require the use of the OVER
clause, which allows PARTITION BY
and ORDER BY
clauses to properly tune the ROW_NUMBER
/RANK
/DENSE_RANK
value returned.
Prior to 9i, the only option was to work with ROWNUM
- which incidentally is faster than using ROW_NUMBER
(link).
Solution 4:
In Oracle 12c, this can be achieved using FETCH..FIRST
ROWS..ONLY
To fetch the top 5 highest salaries.
SELECT *
FROM EMPLOYEES
ORDER BY SALARY DESC
FETCH FIRST 5 ROWS ONLY;