这是什么类型的查询?

时间:2015-08-28 17:18:44

标签: sql sql-server

在我的员工表中,我想找到第三高薪。有人为我提供了以下查询来执行此操作:

SELECT * 
FROM   employee C1 
WHERE  3 = (SELECT Count(DISTINCT( C2.salary )) 
            FROM   employee C2 
            WHERE  C2.salary >= C1.salary) 

此查询有效,但我不知道它是如何工作的。这有什么样的疑问?

4 个答案:

答案 0 :(得分:3)

正如其他人所说,这种类型的查询称为相关子查询。它是一个子查询,因为查询中存在查询并且它是相关的,因为内部查询在其定义中引用外部查询。

考虑内部查询:

SELECT Count(DISTINCT( C2.salary )) 
FROM   employee C2 
WHERE  C2.salary >= C1.salary

从概念上讲,在应用WHERE子句之前,对于外部查询生成的每一行,将对此内部查询求值一次,对employee中的每一行基本上一次。它将生成一个值,即来自employee的行数,其中薪水小于外行的工资。

外部查询将只返回内部查询产生的值正好为3的记录。假设唯一的工资值,employee表中只有一行,其中将有3条记录带有工资值大于或等于它(一行),那一行必然是第三高的工资值。

它很聪明,但不必要的奇怪,可能不像更直接的东西那样最优。

答案 1 :(得分:1)

也许更好的解决方案

SELECT TOP 1 *
FROM (
      SELECT TOP 3 * FROM employee ORDER BY Salary DESC
     ) t
ORDER BY Salary ASC

比相关的子查询更容易阅读和更高效。

答案 2 :(得分:1)

您还可以使用Dense_Rank将薪水排名最低至最低,然后选择排名第3的薪水。如果前2名与我上面的其他答案完全相同,这也会阻止你获得错误的工资。这比具有独特计数的

具有更好看的执行计划
SELECT * 
FROM (
    SELECT  *,
            DENSE_RANK() OVER (ORDER BY Salary DESC) salary_rank
    FROM    employee e
    ) t
WHERE salary_rank = 3

答案 3 :(得分:0)

还可以使用公用表表达式重写它。

WITH top_three
AS
(
    SELECT TOP 3 * FROM employee ORDER BY Salary DESC
)
SELECT TOP 1 *
FROM top_three
ORDER BY Salary ASC;

或者,如果你需要在其中寻找其他等级,你可以使用row_number()。

WITH ranked
AS
(
    SELECT rank = ROW_NUMBER()OVER(ORDER BY Salary DESC), *
    FROM employee
    ORDER BY Salary DESC
)
SELECT *
FROM ranked
WHERE rank = @whatever_rank_you_want;