简体   繁体   中英

Nth max salary query in SQL

I have a table; containing 2 fields, name and salary. I used below script to find the 3rd maximum salary.

SELECT DISTINCT sal 
FROM downtodate1.emp e1  
WHERE 3 = (SELECT COUNT(DISTINCT sal) FROM downtodate1.emp e2 WHERE e1.sal<= e2.sal);

I want to know how it works and why 3 is used here?

select distinct sal 
from downtodate1.emp AS e1  
where 3 = (
    select count(distinct sal) 
    from downtodate1.emp e2 
    where e1.sal <= e2.sal
);

Consider you have a table like this:

sal
---
3
3
2
1
1
0

With this part

select distinct sal 
from downtodate1.emp AS e1 

you'll get the result

sal
---
3
2
1
0

That makes 4 distinct salaries.

Now the subquery

    select count(distinct sal) 
    from downtodate1.emp e2 
    where e1.sal <= e2.sal

is executed for every row in your main query. It calculates the number of distinct values which are lower or equal the row in your main query. So the result of this is actually (but not displayed):

sal | count(distinct sal) where e1.sal <= e2.sal
------------------------------------------------
3     1
3     1
2     2
1     3
1     3
0     4

With the distinct from the main query you'll get this result:

sal | count(distinct sal) where e1.sal <= e2.sal
------------------------------------------------
3     1
2     2
1     3
0     4

and with the WHERE clause 3 = (/*subquery*/) you'll get only

sal | count(distinct sal) where e1.sal <= e2.sal
------------------------------------------------
1     3

this row. So the result is 1 .

Hope it's clear now.

Here's a faster method...

 SELECT salary
   FROM
      (
        SELECT salary
             , @prev := @curr
             , @curr := salary
             , @rank := IF(@prev = @curr, @rank, @rank+1) rank
          FROM employee
         CROSS
          JOIN 
             ( SELECT @curr := null, @prev := null, @rank := 0) sel1
         ORDER 
            BY salary DESC
      ) x
  WHERE rank = 3;

Use This....

SELECT DISTINCT sal FROM downtodate1.emp e1
WHERE 2 = (SELECT COUNT(DISTINCT sal) FROM downtodate1.emp e2 WHERE e1.sal> e2.sal);

WHERE 0 =1st Highest Sal

WHERE 1 =2nd Highest Sal

WHERE 2 =3rd Highest Sal

WHERE 3 =4th Highest Sal

Index start from zero(0)

Instead of this...

SELECT DISTINCT sal FROM downtodate1.emp e1
WHERE 3 = (SELECT COUNT(DISTINCT sal) FROM downtodate1.emp e2 WHERE e1.sal<= e2.sal);

Instead you can use this to find the Nth max salary

SELECT sal FROM emp
ORDER BY sal DESC
LIMIT N,1

N be the Nth number.

Perhaps reformatting the query will clarify:

select distinct sal 
from downtodate1.emp AS e1  
where 3 = (
    select count(distinct sal) 
    from downtodate1.emp e2 
    where e1.sal <= e2.sal
);

The result of the subquery is being compared to 3, as the number of preceding rows for the requried row. This is (potentially) a O(N^2) calculation, but that may be sufficient in this case.

this 3 is the same as you writed

  where  
(select count(distinct sal) from downtodate1.emp e2 where e1.sal <= e2.sal) = 3 ;

where a = 3

or where 3 = the count of distinct sal

使用子查询检索员工最高工资记录的简单方法

select * from Employee where salary in (select max(salary) from Employee)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM