这个查询背后的逻辑工作是什么?

Jas*_*ark 19 sql sql-server

我正在运行以下查询以获得员工表中的第三高薪并且它工作正常,但我无法理解其逻辑.子查询值如何与主查询匹配(左侧部分).有人可以解释一下这个查询背后的逻辑是什么吗?

select e1.salary 
from employee as e1 
where 3 = (select count(salary) 
           from employee as e2 
           where e1.salary<=e2.salary)
Run Code Online (Sandbox Code Playgroud)

PS:我可以理解count()返回的行数(所有记录都是唯一的).

Mar*_*own 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
Run Code Online (Sandbox Code Playgroud)

总结对于employee表中的每一行,它第二次访问该表并计算具有较低或相等工资的行数.如果恰好有3,则会将行添加到结果中.

值得指出的是,如果有多个员工具有相同的薪水,这可能会出错.您可能想要的是具有排名功能的查询.像这样的东西:

SELECT salary
FROM
    (SELECT 
        salary
        ,DENSE_RANK () OVER (ORDER BY salary DESC) [rank]
    FROM employee) t
WHERE
    [rank] = 3
Run Code Online (Sandbox Code Playgroud)

"第三高峰"究竟是什么意思可能有点含糊不清.如果我们有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
Run Code Online (Sandbox Code Playgroud)

如果第三位有一个平局,上面的DENSE_RANK版本也会遇到返回多行的问题.这是否可取取决于究竟需要什么,但可以通过使用工资的汇总函数来减少这种情况.

SELECT MAX(salary)
FROM
    (SELECT 
        salary
        ,DENSE_RANK() OVER (ORDER BY salary desc) [rank]
    FROM employee) t
WHERE
    [rank] = 3
Run Code Online (Sandbox Code Playgroud)


Gio*_*uri 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
Run Code Online (Sandbox Code Playgroud)

因为e1.1有8行e2大于或等于e1.1.

因为e1.2有7行e2大于或等于e1.2.

...

因为e1.6有3行e2大于或等于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
Run Code Online (Sandbox Code Playgroud)

结果在5你的初始选择陈述将导致6我认为根本不是第三高薪.

  • 对大多数人来说,"第三高工资"是指第三高薪人的工资,因此5,6,8,8的预期结果为6. (2认同)

Pரத*_*ீப் 5

employee表中的每个薪水e1都会传递给sub-query. Sub-query会发现所有salaries那些都不及通过salary并计算它.

对于通过的工资,如果子查询返回计数,3那么将产生该工资

考虑员工表中有5条记录

1
2
3
4
5
6
7
8
Run Code Online (Sandbox Code Playgroud)

1从传递e1,子查询会像

select e1.salary 
from employee as e1 
where 3 = (select count(salary) 
           from employee as e2 
           where 1<=e2.salary)
Run Code Online (Sandbox Code Playgroud)

现在子查询中的计数将为8,因为所有记录都大于或等于1.计数不等于3因此salary 1不会返回


2从e1传递时,子查询将是

select e1.salary 
from employee as e1 
where 3 = (select count(salary) 
           from employee as e2 
           where 2<=e2.salary)
Run Code Online (Sandbox Code Playgroud)

现在子查询中的计数将为7,因为除了1以外所有记录都大于或等于2.计数不等于3因此Salary 2不会返回


6从e1传递时,子查询将是

select e1.salary 
from employee as e1 
where 3 = (select count(salary) 
           from employee as e2 
           where 6<=e2.salary)
Run Code Online (Sandbox Code Playgroud)

现在有三个记录大于或等于6(即)6,7,8因此计数将为3且条件满足.所以salary 6将被退回