3

To find out the Nth max sal in oracle i'm using below query

SELECT DISTINCE sal 
FROM emp a 
WHERE (
       SELECT COUNT(DISTINCE sal) 
       FROM emp b 
       WHERE a.sal<=b.sal)=&n;
  • But According to me by using the above query it will take more time to execute if table size is big.

  • i'm trying to use the below query

    SELECT sal 
    FROM (
          SELECT DISTINCE sal 
          FROM emp 
               ORDER BY sal DESC ) 
    WHERE rownum=3;
    
  • but not getting output.. any suggetions please .. Please share any link on how to optimise queries and decrease the time for a query to execute.

Hawk
  • 5,060
  • 12
  • 49
  • 74
Sai
  • 659
  • 4
  • 12
  • 21
  • what's this `DISTINCE` sal or is it DISTINCT ?? – vhadalgi Nov 20 '13 at 09:09
  • 1
    possible duplicate of [Find out the nth-highest salary from table](http://stackoverflow.com/questions/18285903/find-out-the-nth-highest-salary-from-table) – bummi Nov 28 '14 at 18:27

29 Answers29

25

try this

select *
  from
  (
    select
        sal
          ,dense_rank() over (order by sal desc) ranking
    from   table
  )
  where ranking = 4 -- Replace 4 with any value of N
vhadalgi
  • 7,027
  • 6
  • 38
  • 67
  • 2
    if two persons have same salary they must given same rank,so `dense_rank` must be used in this case – vhadalgi Nov 20 '13 at 09:02
  • can we use rank() in place of that? – Sai Nov 20 '13 at 09:21
  • The DENSE_RANK function acts like the RANK function except that it assigns consecutive ranks.[see here](http://stackoverflow.com/questions/11183572/whats-the-difference-between-rank-and-dense-rank-functions-in-oracle) – vhadalgi Nov 20 '13 at 09:24
  • @SaiDattu [check out here for cpu_time](http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2920665938600) – vhadalgi Nov 20 '13 at 09:27
  • one more doubt please... in the above query we can see only sal col in the result set.. if i want to see to see entire columns..any help?? – Sai Nov 20 '13 at 10:10
  • @vhadalgi Hi, I am getting this error.... Error Code: 1248. Every derived table must have its own alias – CodeWorld Mar 02 '22 at 09:10
6
SELECT sal FROM (
    SELECT sal, row_number() OVER (order by sal desc) AS rn FROM emp
)
WHERE rn = 3

Yes, it will take longer to execute if the table is big. But for "N-th row" queries the only way is to look through all the data and sort it. It will be definitely much faster if you have an index on sal.

Kombajn zbożowy
  • 8,755
  • 3
  • 28
  • 60
  • 2
    You need to use `desc` on order by, And as OP need the distinct salary , a group by salary would be useful for non repeating ranked salary. – ajmalmhd04 Nov 20 '13 at 08:55
  • 2
    It's important to note the differences between `row_number`, `rank`, and `dense_rank` for this specific requirement. What should happen when you have more then one person with the same salary ? should you count them in the same position ... ? – haki Nov 20 '13 at 09:00
  • @Kombajn zbożowy here if the salaries are like 5000,3000,5000,3000,2000 then will it generate wrong output?? – Sai Nov 20 '13 at 09:07
  • Well, it depends on the exact behaviour you need. For salaries: 5000,3000,5000,3000,2000 I would say the answer is 3000 (and my query works like this). But you might want 2000 (3rd *unique* salary), in this case right, you would need to rebuild the query. – Kombajn zbożowy Nov 20 '13 at 09:52
  • Right, should have been order by sal *desc*, that's just a typo, edited. – Kombajn zbożowy Nov 20 '13 at 09:53
5
SELECT * 
FROM Employee Emp1
WHERE (N-1) = ( 
SELECT COUNT(DISTINCT(Emp2.Salary))
FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary)
Raging Bull
  • 18,593
  • 13
  • 50
  • 55
siva
  • 51
  • 1
  • 1
2

This will show the 3rd max salary from table employee. If you want to find out the 5th or 6th (whatever you want) value then just change the where condition like this where rownum<=5" or "where rownum<=6 and so on...

select min(sal) from(select distinct(sal) from emp  where rownum<=3 order by sal desc);
Tony Babarino
  • 3,355
  • 4
  • 32
  • 44
Hasnain Latif
  • 55
  • 1
  • 10
  • Correction needed : where clause should be in the outside query.. it should be : select min(sal) from(select distinct(sal) from emp order by sal desc) where rownum<=3; – abhi Jul 03 '18 at 10:52
2
SELECT Min(sal)
FROM   (SELECT DISTINCT sal
        FROM   emp
        WHERE  sal IS NOT NULL
        ORDER  BY sal DESC)
WHERE  rownum <= n;  
Pratham
  • 1,522
  • 1
  • 18
  • 33
Sneha
  • 21
  • 1
1

We could write as below mentioned also.

select min(sal) from (select sal from emp where rownum=<&n order by sal desc);
Stevoisiak
  • 23,794
  • 27
  • 122
  • 225
Yash
  • 634
  • 1
  • 6
  • 17
1

These queries will also work:

Workaround 1)

SELECT ename, sal 
FROM Emp e1 WHERE n-1 = (SELECT COUNT(DISTINCT sal) 
                         FROM Emp e2 WHERE e2.sal > e1.sal)

Workaround 2) using row_num function.

SELECT * 
FROM ( 
   SELECT e.*, ROW_NUMBER() OVER (ORDER BY sal DESC) rn FROM Emp e 
) WHERE rn = n;

Workaround 3 ) using rownum pseudocolumn

Select MAX(SAL) 
from (
   Select * 
   from (
      Select * 
      from EMP 
      order by SAL Desc
   ) where rownum <= n
)
1

The following solution works from 12c onwards:

Select min(sal) from emp where 
Sal in ( select distinct (sal) from emp order by sal desc fetch first n rows only);

Replace n as per your requirement

Irina Avram
  • 1,492
  • 2
  • 20
  • 35
1

In my case this Query is successfully executed (Oracle).

select salary from 
(select salary, (dense_rank() 
over (order by salary desc)) R 
from employees)  
where R='10' group by salary;

you can replace value '10' by any value of 'n'.

0
 SELECT sal
    FROM (
                SELECT empno,
                             deptno, sal,
                              dense_rank( ) over ( partition by deptno order by sal desc) NRANK
                FROM emp
            )
    WHERE NRANK = 4
Anant_00
  • 133
  • 1
  • 5
0
SELECT *
    FROM (
                SELECT empno,
                       deptno, sal,
                       dense_rank( ) over ( order by sal desc) NRANK
                FROM emp
            )
    WHERE NRANK = 4
Anant_00
  • 133
  • 1
  • 5
0

you can replace the 2 with your desired number

select * from ( select distinct (sal),ROW_NUMBER() OVER (order by sal desc) rn from emp ) where rn=2
Kishore Kumar
  • 909
  • 2
  • 10
  • 15
0

Now you try this you will get for sure:

SELECT DISTINCT sal 
    FROM emp a 
    WHERE (
           SELECT COUNT(DISTINCT sal) 
           FROM emp b 
           WHERE a.sal<=b.sal)=&n;

For your information, if you want the nth least sal:

SELECT DISTINCT sal 
FROM emp a 
WHERE (
       SELECT COUNT(DISTINCT sal) 
       FROM emp b 
       WHERE a.sal>=b.sal)=&n;
serenesat
  • 4,611
  • 10
  • 37
  • 53
hemanth
  • 1
  • 1
0

Refer following query for getting nth highest salary. By this way you get nth highest salary. If you want get nth lowest salary only you need to replace DESC by ASC in the query. for getting highest salary of employee.

Vijay Bhatt
  • 1,351
  • 13
  • 13
0

select min(sal) from (select distinct sal from employee order by sal DESC) where rownum<=N;

place the number whatever the highest sal you want to retrieve.

mahesh
  • 19
  • 2
  • 7
0

Try out following:

SELECT *
FROM
  (SELECT rownum AS rn,
    a.*
  FROM
    (WITH DATA AS -- creating dummy data
    ( SELECT 'MOHAN' AS NAME, 200 AS SALARY FROM DUAL
    UNION ALL
    SELECT 'AKSHAY' AS NAME, 500 AS SALARY FROM DUAL
    UNION ALL
    SELECT 'HARI' AS NAME, 300 AS SALARY FROM DUAL
    UNION ALL
    SELECT 'RAM' AS NAME, 400 AS SALARY FROM DUAL
    )
  SELECT D.* FROM DATA D ORDER BY SALARY DESC
    ) A
  )
WHERE rn = 3; -- specify N'th highest here (In this case fetching 3'rd highest)

Cheers!

Akshay Lokur
  • 6,680
  • 13
  • 43
  • 62
0
select * FROM (
select EmployeeID, Salary
, dense_rank() over (order by Salary DESC) ranking
from Employee
)
WHERE ranking = N;

dense_rank() is used for the salary has to be same.So it give the proper output instead of using rank().

Md Wasi
  • 479
  • 3
  • 16
0
SELECT TOP (1) Salary FROM
(
    SELECT DISTINCT TOP (10) Salary FROM Employee ORDER BY Salary DESC
) AS Emp ORDER BY Salary

This is for 10th max salary, you can replace 10 with n.

Abhijeet Ahuja
  • 5,596
  • 5
  • 42
  • 50
0

This will also work :

with data as 
(
select sal,rwid from (
select salary as sal,rowid as rwid from salary order by salary desc
)
where rownum < 5
)
select * from salary a 
where rowid = (select min(rwid) from data)
Shri
  • 27
  • 1
  • 8
0
select min(sal) from (select distinct(sal) from emp  order by sal desc) where rownum <=&n;

Inner query select distinct(sal) from emp order by sal desc will give the below output as given below.

SAL 5000 3000 2975 2850 2450 1600 1500 1300 1250 1100 950 800

without distinct in the above query select sal from emp order by sal desc output as given below.

SAL 5000 3000 3000 2975 2850 2450 1600 1500 1300 1250 1250 1100 950 800

outer query will give the 'N'th max sal (E.g) I have tried here for 4th Max sal and out put as given below.

MIN(SAL) 2850

Avag Sargsyan
  • 2,437
  • 3
  • 28
  • 41
0
Select min(salary) from (
  select distinct(salary) from empdetails order by salary desc
) where rownum <=&rn

Just enter nth number which you want.

Petter Friberg
  • 21,252
  • 9
  • 60
  • 109
0

Try this:

SELECT min(sal)  FROM (
SELECT sal FROM emp ORDER BY sal desc) WHERE ROWNUM <= 3; -- Replace 3 with any value of N
0

You can optimize the query using Dense_rank() function.

for Example :

select distinct salary from ( select salary ,dense_rank() over (order by salary desc) ranking from Employee ) where ranking = 6

Note: ranking 6 is the number of nth order.

Vinay
  • 41
  • 3
0
select * from (select rownum as rownumber,emp1.* from (select * from emp order by sal desc) emp1) where rownumber = 3;
Plutian
  • 2,276
  • 3
  • 14
  • 23
  • 4
    Hi and welcome to stackoverflow, and thank you for answering. While this code might answer the question, can you consider adding some explanation for what the problem was you solved, and how you solved it? This will help future readers to understand your answer better and learn from it. – Plutian Feb 19 '20 at 16:39
0

Try this one :

Select sal 
From (Select rownum as rank, empno,ename,sal
      From (Select * 
            From emp order by sal desc)
      ) 
where rank=2;

Just add the number as rank which will give you nth highest salary.

Amirhossein
  • 1,148
  • 3
  • 15
  • 34
0
SELECT MIN(Salary) salary
FROM    (
            SELECT DISTINCT Salary 
            FROM Employee
            ORDER BY Salary DESC
        )
WHERE ROWNUM <= n
ORDER BY salary ASC;

-- replace "n" from line number 7 with anything you want

0

select MIN(salary) from (select distinct salary from employees order by SALARY DESC) WHERE ROWNUM <= 3;

-1

5th highest salary:

SELECT
    * 
FROM
    emp a 
WHERE 
    4 = (
        SELECT 
            COUNT(DISTINCT b.sal) 
        FROM 
            emp b 
        WHERE 
            a.sal < b.sal
    )

Replace 4 with any value of N.

dhh
  • 4,289
  • 8
  • 42
  • 59
  • 1
    It would be helpful to give an answer that contains full code (correctly formatted) and an explanation why your answer provides a solution. What is to learn from this? – Timusan Jul 06 '15 at 06:24
-1

There are three methods are there...

SELECT salary,first_name,rnk 
FROM (SELECT salary,first_name,rank() over (order by salary desc nulls last) as                                                                  rnk from emp) where rnk=3;


SELECT salary,first_name,rnk 
FROM (SELECT salary,first_name,dense_rank() over (order by salary desc nulls last) as                                                                  rnk from emp) where rnk=3;


select rnk,first_name,salary 
from (select rownum as rnk ,first_name,salary 
      from (select first_name,salary 
            from emp order by salary desc nulls last)) where rnk=3
HaveNoDisplayName
  • 8,291
  • 106
  • 37
  • 47