Home > T - SQL > Nth Highest Salary Query

Nth Highest Salary Query


Problem: Show the list of all employees from the employee table having second highest Salary or Nth highest salary in the organization.

Solution: Well we can achieve the result by so many ways but in this post I would like to do it by using co-related queries.  Co-related queries are very interesting stuff as it gives you option to process data row wise. But at the same time it has a big drawback. Row wise processing causes bottle neck for the performance of the query.

Query to get the list of employees getting 2nd highest salary (Set the value of @SalaryPosition to get Nth highest salary):

DECLARE @SalaryPosition int
SET @SalaryPosition = 2
SELECT *
FROM Employee E1
WHERE @SalaryPosition =  
          (
            SELECT COUNT(DISTINCT E2.Salary) 
            FROM Employee E2
            WHERE E2.Salary >= E1.Salary
          )

Well the query looks simple but understanding it is little bit complex. Let’s explore the process behind it.

I have taken the variable @SalaryPosition in order to make it standardize while checking salaries in more than one level.

Before going further, let me tell you the concept behind the co-related query.




Co-Related Query:  In short, it’s a type of nested sub query where the inner query is referenced to some value of the outer query. And the inner query is executed for each record in the outer query making it slowL. More appropriate example of a Co-Related query is the IN () operator.

In our query, to get the 2nd highest salary, works in the same way too. Let’s dive a little deeper.

Sample data used in employee table:

slNo empname salary

101

Ram

5000

102

Abhishek

7500

101

kumar

5000

104

prasad

6570

102

Jumla

7500

101

Harkesh

12000

101

John

4000


 

Run the below query to create the table in your database and to insert data into it.

CREATE TABLE [dbo].[employee](
	[slNo] [int] NULL,
	[empname] [varchar](50) NULL,
	[salary] [float] NULL
)
INSERT INTO [dbo].[employee]([slNo],[empname],[salary])
select '101', 'Ram', '5000' Union All
select '102', 'Abhishek', '7500' Union All
select '101', 'kumar', '5000' Union All
select '104', 'prasad', '6570' Union All
select '102', 'Jumla', '7500' Union All
select '101', 'Harkesh', '12000' Union All
select '101', 'John', '4000'

So we have taken two aliases for the employee table i.e. E1 and E2.

Employee table split 

Now let’s see how to get the employee names getting 2nd highest salary.

Query:

DECLARE @SalaryPosition int
SET @SalaryPosition = 2
SELECT *
FROM Employee E1
WHERE @SalaryPosition =  
           (
             SELECT COUNT(DISTINCT E2.Salary) 
             FROM Employee E2
             WHERE E2.Salary >= E1.Salary
           )

Here E1 is the outer query and E2 is the inner query.




Corollary: Let’s take the first record in the table E1 where the salary is 5000 and assume it as the second highest salary. But how will you know if it is actually the second highest salary or not. If 5000 is the second highest salary, then the distinct count of all the salaries from table E2 which are greater than or equal to 5000 must be 2.

Employee table pointing to 5000 

The first record from E1 (salary = 5000) will be compared to all the records in E2 (salary).

Table E1  (considering the first record only) Table E2 (distinct salary) Distinct count where salary is >= 5000

5000

4000
5000
6570
7500
12000

 

 

4

 

 

Hence 5000 is not the highest salary as we have 4 more salaries greater than equal to 5000. But it is concluded that 5000 is at the fourth position.

Now let’s take the second salary from table E1 and do the same comparison as in the earlier case.

Employee table pointing to 7500 

The second salary is 7500 and as per rule the count of distinct salaries greater than equal to 7500 must be 2.

Table E1  (considering the second record only) Table E2 (distinct salary) Distinct count where salary is >= 5000

7500

4000
5000
6570
7500
12000

 

 

2

 

 

 

Here in this case our condition in the where clause of outer query is satisfying. Let’s dissect the query for this particular case.

Original Query:

DECLARE @SalaryPosition int
SET @SalaryPosition = 2
SELECT *
FROM Employee E1
WHERE @SalaryPosition =  
           (
            SELECT COUNT(DISTINCT E2.Salary) 
            FROM Employee E2
            WHERE E2.Salary >= E1.Salary
           )

Step 1:

SELECT *
FROM Employee E1
WHERE 2 =  
           (
             SELECT COUNT(DISTINCT E2.Salary) 
             FROM Employee E2
             WHERE E2.Salary >= E1.Salary
           )

Step2: (where the salary is 7500, inner query will return 2 as only two salaries are there in table E2 that are greater than equal to 7500.)

SELECT *
FROM Employee E1
WHERE 2 =  
              (
                2
              )

Step3: (Now 2 = 2, the outer query condition satisfies, hence it will return the corresponding record in the result set.

Flow of query 

Once it returns the record 101, Abhishek, 7500 it will iterate through other records in table E1 to check if any other record is satisfying the same condition. In our example two records satisfies the condition “where 2=2”, hence both the records returned to the result set.

Finally we got all the employee information with second highest salary.

If you want to check for highest salary or second highest salary, then just change the value of @SalaryPosition accordingly.

Other ways to get list of employees getting 2nd highest salary in the organization are:

select * from (
                    select DENSE_RANK() OVER(order by salary desc) as RankID, * from dbo.Employee ) InnQ
            where InnQ.RankID = 2

 

select * from dbo.Employee where salary = 
	(
		SELECT max(salary) FROM dbo.Employee WHERE salary < 
		(SELECT max(salary) FROM dbo.Employee)
	)

 

select * from dbo.Employee where salary = 
	(	
		Select max(salary) from dbo.Employee where salary NOT IN 
		(Select max(salary) from dbo.Employee)
	)

Let us know your valuable feedback on the above methodology.

Categories: T - SQL
  1. joestudent
    July 14th, 2010 at 17:05 | #1

    very well articulated. thanks

  2. krishstr
    July 14th, 2010 at 17:07 | #2

    Thanks a lot for this article. finally i understood, how co-related queries are working. keep it up boss.

  3. pandukrs
    July 14th, 2010 at 17:21 | #3

    A truly fantastic idea and approach.
    I look forward for ur upcoming posts.

  4. Andrew
    July 14th, 2010 at 23:21 | #4

    Nice post. All very good points.
    There are a few sites that I’ve registered, but there are only few who explain any problem so elaborately.
    Thanks

  5. Iarfhlaith
    July 15th, 2010 at 11:24 | #5

    What a brilliant post Arun! You should do a series! :) very good explanation. Expecting some more posts like this.

  6. Nageswara Rao
    September 23rd, 2010 at 14:04 | #6

    Hi Arun,

    Excellent Post.Spoon feeding explanation.Please post many articles like this

  7. March 15th, 2011 at 22:25 | #7

    Arun

    FINALLY i got the exact info what I am searching for since many days

    Thanks for the detailed explanation

    Great Job

    Thanks
    Sunil

  8. May 10th, 2011 at 18:05 | #8

    Great post written keeping average SQL user in view!!

  9. Mahesh Khadse
    May 12th, 2011 at 16:07 | #9

    Hi Arun,

    How simply you explain the concept is excellent… only on a single read everything is clear and its clear the other concept too(depends on individuals.) :) .

    Thanks for the post and simple explanation.

    You proved simplicity is the best…:)

    Mahesh Khadse

  10. Amardeep daharvan
    May 19th, 2011 at 10:38 | #10

    thanx for explain in step by step..

  11. Mukund
    June 9th, 2011 at 17:38 | #11

    Hi,
    but below query gives all the records from employee table.
    i agree with you till nested query. but what after getting the count from nested query. According to you it will be llike below one.
    but plz check the output of below query….

    SELECT *
    FROM Employee E1
    WHERE 2 =
    (
    2
    )

  12. umesh
    July 6th, 2011 at 16:29 | #12

    Hi,very good post but please check the out put of that

    SELECT *
    FROM Employee E1
    WHERE 2 =
    (
    2
    )

  13. July 6th, 2011 at 21:11 | #13

    @Mukund and @umesh,
    I know it will return all the records, the steps I shown above is the illustration of internal working of co-related query. Please have a look closely on all the steps, by the time it will come to Step 2:, the outer query will have only one record, hence it will return only one record to the final result set.

    Thanks,
    Arun

  14. Ranjan Kumar Naik
    July 18th, 2011 at 17:56 | #14

    The explanation is simple but excellent and even professors cannot explain in such a simplest way. This is what I am looking for in my current project. Thank you…

    Regards,
    Ranjan Kumar

  15. Ranjan Kumar Naik
    July 18th, 2011 at 18:03 | #15

    Hi Arun,
    Can you please post an article explaining the Lazy loading process in ORM mapping (Object Relational Mapping) in terms of space-time complexity? I am looking for it to use in our project.

    Regards
    Ranjan

  16. Big B
    August 10th, 2011 at 17:32 | #16

    @Mukund
    You can with details that Arun had explained,
    Second query will be serching to distincts from the salary.

  17. pavan
    August 19th, 2011 at 15:03 | #17

    Superb explanation can u explain joins with examples?

    Thanks in advance
    pavan

  18. Mamta
    August 25th, 2011 at 09:08 | #18

    Hi, This helped me alot to understand the concept of how to find Nth highest salary. explainations is very supportive .

    Thanks alot Amit !!

  19. Ankur
    August 31st, 2011 at 23:12 | #19

    Thanks a lot! for nice explanation ! i was searching for it for long time..

  20. September 12th, 2011 at 23:20 | #20

    a nice explanation.
    I was searching for explanation more then 6 months.

  21. Ankit Mishra
    October 12th, 2011 at 15:09 | #21

    thanks..for explaining this step by step…..

  22. subash
    October 28th, 2011 at 11:40 | #22

    thank for well define step by step explaining

  23. nagender
    November 1st, 2011 at 20:06 | #23

    Excellent Explanation

  24. Rajesh
    November 1st, 2011 at 20:53 | #24

    Excellent Explanation

  25. tanuja
    November 19th, 2011 at 20:58 | #25

    Detailed and wellpresented explanation

  26. Rajesh Yadav
    November 20th, 2011 at 12:05 | #26

    Hi,
    Now,this tricky query very clear,I gave interview in IT Industry around 2 years and this query put up every time but I can’t able to explain him exactly.
    Today, I am very very happy to clear concept on this query.
    Thank You So Much.
    Very Nice Article…Thanks again…
    Regards,
    Rajesh

  27. Aditya Joshi
    November 23rd, 2011 at 17:24 | #27

    This is very crisp and crystal clear.
    Thank You so much.

  28. Vikas
    December 20th, 2011 at 21:53 | #28

    Hi Arun,

    I was looking for explanation of this query :-) . Thanks for nice explanation.

    Please give me your email id or tell me any other way so that i can discuss my doubts with you directly (if possible).

    Thanks.

  29. farhan
    January 13th, 2012 at 16:07 | #29

    good job man. this really helped a lot

  30. ash
    January 24th, 2012 at 18:38 | #30

    thx :)

  31. John faruki
    February 9th, 2012 at 17:44 | #31

    U certainly owe one from us… Brilliant is not the word for U.. Thanks John Faruki

  32. sridhar
    February 14th, 2012 at 13:58 | #32

    Nice Query. Never seen such explanation.

  33. Hari
    March 2nd, 2012 at 16:00 | #33

    nice article.Thanks

  34. ramakrishna
    March 9th, 2012 at 14:49 | #34

    hi..its clear and simple..thanks..

  35. Shalabh Saxena
    March 27th, 2012 at 22:36 | #35

    God Job Man. Its a nice way you explain quite simplest complex query..

  36. Narasimha
    April 11th, 2012 at 11:22 | #36

    Super……….& …thanks………

  37. Manoj
    April 17th, 2012 at 16:05 | #37

    @joestudent
    Thanks For Explanation.It’s Very well article.

  38. Suchita
    April 19th, 2012 at 22:52 | #38

    What an explanation. Very well explained.
    Thanks, I was searching for such an article for so long.

  39. prakash
    May 15th, 2012 at 11:11 | #39

    Awesome dude………!u r Rocking……!

  40. prakash
    May 15th, 2012 at 11:37 | #40

    plz correct that ..in second table that should be >=7500………thank you

  1. No trackbacks yet.