我正在运行以下查询以获得员工表中的第三高薪并且它工作正常,但我无法理解其逻辑。子查询值如何与主查询匹配(左侧部分)。有人可以解释一下这个查询背后的逻辑是什么吗?
select e1.salary
from employee as e1
where 3 = (select count(salary)
from employee as e2
where e1.salary<=e2.salary)
PS:我可以理解count()
返回行数(所有记录都是唯一的)。
答案 0 :(得分:21)
这个查询基本上是这样说的:
for each row in employee assign to e1
count = 0
for each row in employee assign to e2
if e1.salary <= e2.salary
count = count + 1
end if
end for
if count = 3
add e1 to result set
end if
end for
return result set
总结对于employee表中的每一行,它第二次访问该表并计算具有较低或相等工资的行数。如果恰好有3,则会将行添加到结果中。
值得指出的是,如果有多个员工的薪水相同,这可能会出错。您可能想要的是具有排名功能的查询。像这样:
SELECT salary
FROM
(SELECT
salary
,DENSE_RANK () OVER (ORDER BY salary DESC) [rank]
FROM employee) t
WHERE
[rank] = 3
&#34;第三高的&#34;究竟是什么意思?也许有点含糊不清。如果我们有8,8,6,5的工资,则上述将返回5.如果我们想要6,您需要将DENSE_RANK更改为ROW_NUMBER,如下所示:
SELECT salary
FROM
(SELECT
salary
,ROW_NUMBER () OVER (ORDER BY salary DESC) [rank]
FROM employee) t
WHERE
[rank] = 3
如果第三名出现并列,则上面的DENSE_RANK版本也会遇到多行返回的问题。这是否可取取决于究竟需要什么,但可以通过使用工资的汇总函数来减少这一点。
SELECT MAX(salary)
FROM
(SELECT
salary
,DENSE_RANK() OVER (ORDER BY salary desc) [rank]
FROM employee) t
WHERE
[rank] = 3
答案 1 :(得分:6)
考虑以下这些值:
Salary:
1
2
3
4
5
6
7
8
e1 e2
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
对于e1.1
,e2
中有8行大于或等于e1.1
。
对于e1.2
,e2
中有7行大于或等于e1.2
。
...
对于e1.6
,e2
中有3行大于或等于e1.6
。
这是一个非常奇怪和令人困惑的选择声明。我只想使用DENSE_RANK
窗口函数重写它,因为如果你有几行具有相同的工资,你将得不到正确的结果:
DECLARE @t TABLE ( i INT )
INSERT INTO @t
VALUES ( 1 ),
( 2 ),
( 3 ),
( 4 ),
( 5 ),
( 6 ),
( 8 ),
( 8 );
WITH cte
AS ( SELECT * ,
DENSE_RANK() OVER ( ORDER BY i DESC ) AS rn
FROM @t
)
SELECT *
FROM cte
WHERE rn = 3
5
的结果,而您的初始选择语句将导致6
我认为根本不是第三高薪。
答案 2 :(得分:5)
employee
表e1
中的每个薪水都会传递给sub-query
。
Sub-query
会发现所有salaries
小于传递的salary
并计算它。
如果子查询返回计数为3
,则传递的工资将导致该工资
考虑员工表中有5条记录
1
2
3
4
5
6
7
8
从1
传递e1
时,子查询将类似于
select e1.salary
from employee as e1
where 3 = (select count(salary)
from employee as e2
where 1<=e2.salary)
现在子查询中的计数将为8,因为所有记录都大于或等于1.计数不等于3,因此不会返回salary 1
从e1传递2
时,子查询将类似于
select e1.salary
from employee as e1
where 3 = (select count(salary)
from employee as e2
where 2<=e2.salary)
现在子查询中的计数将为7,因为除了1之外所有记录都大于或等于2.计数不等于3所以Salary 2
它不会被返回
从e1传递6
时,子查询将类似于
select e1.salary
from employee as e1
where 3 = (select count(salary)
from employee as e2
where 6<=e2.salary)
现在有三个记录大于或等于6(即)6,7,8所以计数将为3且条件满足。因此将返回salary 6
答案 3 :(得分:1)
事实上它非常简单。第二个查询选择当前(选定)员工(e1)工资较低的所有员工。然后我们说薪水较低或相等的员工数量需要为3.这导致获得第三高工资。