SQL查询从工资表中查找第N个最高薪水

Nov*_*Net 24 sql t-sql sql-server

如何在包含SQL Server工资的表中找到第N个最高工资?

Lit*_*les 33

您可以使用公用表表达式(CTE)来获得答案.

假设您在工资表中有以下工资:

 EmployeeID  Salary
--------------------
     10101   50,000
     90140   35,000
     90151   72,000
     18010   39,000
     92389   80,000
Run Code Online (Sandbox Code Playgroud)

我们将使用:

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
Run Code Online (Sandbox Code Playgroud)

这将按照Salary按降序排序后为每一行创建一个行号,然后检索第三行(包含第三高的记录).


对于那些不想要CTE(或陷入SQL 2000)的人:

[ 注意:这比上面的例子明显更糟; 与exceution计划并排运行它们显示CTE的查询成本为36%,子查询的查询成本为64%]:

SELECT TOP 1 Salary
FROM 
(
    SELECT TOP N Salary
    FROM Salaries
    ORDER BY Salary DESC
) SalarySubquery
ORDER BY Salary ASC
Run Code Online (Sandbox Code Playgroud)

其中N由您定义.

SalarySubquery 是我给子查询的别名,或括号中的查询.

子查询的作用是选择前N个工资(在这种情况下我们会说3个),并按最高工资对它们进行排序.

如果我们想要查看第三高的薪水,子查询将返回:

 Salary
-----------
80,000
72,000
50,000
Run Code Online (Sandbox Code Playgroud)

外部查询然后从子查询中选择第一个薪水,除了我们这次按升序排序,从最小到最大排序,因此50,000将是第一个按升序排序的记录.

如您所见,50,000例确实是该示例中第三高的薪水.


And*_*mar 12

您可以使用row_number选择特定行.例如,第42个最高薪水:

select  *
from    (
        select  row_number() over (order by Salary desc) as rn
        ,       *
        from    YourTable
        ) as Subquery
where   rn = 42
Run Code Online (Sandbox Code Playgroud)

窗口函数row_number只能出现在selectorder by子句中.解决方法是将row_number子查询放在子查询中.


小智 6

select MIN(salary) from (
select top 5 salary from employees order by salary desc) x
Run Code Online (Sandbox Code Playgroud)


小智 5

EmpID   Name    Salary
1   A   100
2   B   800
3   C   300
4   D   400
5   E   500
6   F   200
7   G   600

SELECT * FROM Employee E1
WHERE (N-1) = (
                SELECT COUNT(DISTINCT(E2.Salary))
                FROM Employee E2
                WHERE E2.Salary > E1.Salary
              )
Run Code Online (Sandbox Code Playgroud)

假设您想找到第五高的薪水,这意味着总共有4名员工的薪水高于第五高的员工。因此,对于外部查询的每一行,请检查比当前薪水高的薪水总数。外部查询将首先使用100,并检查薪水数量是否大于100。它将为6,与外部查询的(5-1) = 6where子句不匹配。然后,对于800,检查薪水数量是否大于800,为4=0false,然后为300工作,最后表中总共有4个记录大于300。因此,4=4将满足where子句并返回 3 C 300