SQL query to find Nth highest salary from a salary table

前端 未结 11 2174
隐瞒了意图╮
隐瞒了意图╮ 2020-11-28 10:45

How can I find the Nth highest salary in a table containing salaries in SQL Server?

相关标签:
11条回答
  • 2020-11-28 11:13

    You could use row_number to pick a specific row. For example, the 42nd highest salary:

    select  *
    from    (
            select  row_number() over (order by Salary desc) as rn
            ,       *
            from    YourTable
            ) as Subquery
    where   rn = 42
    

    Windowed functions like row_number can only appear in select or order by clauses. The workaround is placing the row_number in a subquery.

    0 讨论(0)
  • 2020-11-28 11:17

    Solution 1: This SQL to find the Nth highest salary should work in SQL Server, MySQL, DB2, Oracle, Teradata, and almost any other RDBMS: (note: low performance because of subquery)

    SELECT * /*This is the outer query part */
    FROM Employee Emp1
    WHERE (N-1) = ( /* Subquery starts here */
    SELECT COUNT(DISTINCT(Emp2.Salary))
    FROM Employee Emp2
    WHERE Emp2.Salary > Emp1.Salary)
    

    The most important thing to understand in the query above is that the subquery is evaluated each and every time a row is processed by the outer query. In other words, the inner query can not be processed independently of the outer query since the inner query uses the Emp1 value as well.

    In order to find the Nth highest salary, we just find the salary that has exactly N-1 salaries greater than itself.


    Solution 2: Find the nth highest salary using the TOP keyword in SQL Server

    SELECT TOP 1 Salary
    FROM (
          SELECT DISTINCT TOP N Salary
          FROM Employee
          ORDER BY Salary DESC
          ) AS Emp
    ORDER BY Salary
    

    Solution 3: Find the nth highest salary in SQL Server without using TOP

    SELECT Salary FROM Employee 
    ORDER BY Salary DESC OFFSET N-1 ROW(S) 
    FETCH FIRST ROW ONLY
    

    Note that I haven’t personally tested the SQL above, and I believe that it will only work in SQL Server 2012 and up.

    0 讨论(0)
  • 2020-11-28 11:21
    select MIN(salary) from (
    select top 5 salary from employees order by salary desc) x
    
    0 讨论(0)
  • 2020-11-28 11:21

    Simple way WITHOUT using any special feature specific to Oracle, MySQL etc. Suppose in EMPLOYEE table Salaries can be repeated. Use query to find out rank of each ID.

    select  *
    from  (
    select tout.sal, id, (select count(*) +1 from (select distinct(sal) distsal from     
    EMPLOYEE ) where  distsal >tout.sal)  as rank  from EMPLOYEE tout
    ) result
    order by rank
    

    First we find out distinct salaries. Then we find out count of distinct salaries greater than each row. This is nothing but the rank of that id. For highest salary, this count will be zero. So '+1' is done to start rank from 1.

    Now we can get IDs at Nth rank by adding where clause to above query.

    select  *
    from  (
    select tout.sal, id, (select count(*) +1 from (select distinct(sal) distsal from     
    EMPLOYEE ) where  distsal >tout.sal)  as rank  from EMPLOYEE tout
    ) result
    where rank = N;
    
    0 讨论(0)
  • 2020-11-28 11:22

    You can use a Common Table Expression (CTE) to derive the answer.

    Let's say you have the following salaries in the table Salaries:

     EmployeeID  Salary
    --------------------
         10101   50,000
         90140   35,000
         90151   72,000
         18010   39,000
         92389   80,000
    

    We will use:

    DECLARE @N int
    SET @N = 3  -- Change the value here to pick a different salary rank
    
    SELECT Salary
    FROM (
        SELECT row_number() OVER (ORDER BY Salary DESC) as SalaryRank, Salary
        FROM Salaries
    ) as SalaryCTE
    WHERE SalaryRank = @N
    

    This will create a row number for each row after it has been sorted by the Salary in descending order, then retrieve the third row (which contains the third-highest record).

    • SQL Fiddle

    For those of you who don't want a CTE (or are stuck in SQL 2000):

    [Note: this performs noticably worse than the above example; running them side-by-side with an exceution plans shows a query cost of 36% for the CTE and 64% for the subquery]:

    SELECT TOP 1 Salary
    FROM 
    (
        SELECT TOP N Salary
        FROM Salaries
        ORDER BY Salary DESC
    ) SalarySubquery
    ORDER BY Salary ASC
    

    where N is defined by you.

    SalarySubquery is the alias I have given to the subquery, or the query that is in parentheses.

    What the subquery does is it selects the top N salaries (we'll say 3 in this case), and orders them by the greatest salary.

    If we want to see the third-highest salary, the subquery would return:

     Salary
    -----------
    80,000
    72,000
    50,000
    

    The outer query then selects the first salary from the subquery, except we're sorting it ascending this time, which sorts from smallest to largest, so 50,000 would be the first record sorted ascending.

    As you can see, 50,000 is indeed the third-highest salary in the example.

    0 讨论(0)
提交回复
热议问题