在我的员工表中,我想找到第三高薪。有人为我提供了以下查询来执行此操作:
SELECT *
FROM employee C1
WHERE 3 = (SELECT Count(DISTINCT( C2.salary ))
FROM employee C2
WHERE C2.salary >= C1.salary)
此查询有效,但我不知道它是如何工作的。这有什么样的疑问?
答案 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;