【问题标题】:Self Join with Correlated Subquery具有相关子查询的自联接
【发布时间】:2018-07-07 12:28:08
【问题描述】:

我需要找到一个薪水高于其经理的员工。为此,我曾经使用以下查询并且它有效;

选择 e1.EmpID ,e1.EmpName ,e1.EmpSalary ,e1.ManagerID FROM empalary e 内部加入 empsalary e1 ON e.EmpID = e1.ManagerID 在哪里 e1.EmpSalary > e.EmpSalary

但是跟随一个不起作用。我想知道为什么不是?为什么它的结果为空?正确的格式应该是什么?

SELECT * 
FROM empsalary as e
WHERE e.empsalary=(
                   SELECT e1.empsalary 
                   FROM empsalary as e1 
                   WHERE e.EmpID = e1.ManagerID 
                   AND e1.EmpSalary > e.EmpSalary)

此处是示例数据和代码;

EmpID       EmpName    EmpSalary            ManagerID
----------- ---------- -------------------- -----------
1           Neevan     100000               6
2           Mukesh     30000                6
3           Disha      50000                6
4           Martin     90000                6
5           Roy        170000               6
6           Anvesh     168000               NULL



CREATE TABLE empsalary
(
    EmpID INT
    ,EmpName VARCHAR(10)
    ,EmpSalary BIGINT
    ,ManagerID INT 
)

INSERT INTO empsalary
VALUES
(1,'Neevan',100000,6)
,(2,'Mukesh',30000,6)
,(3,'Disha',50000,6)
,(4,'Martin',90000,6)
,(5,'Roy',170000,6)
,(6,'Anvesh',168000,NULL)

【问题讨论】:

    标签: sql sql-server self-join correlated-subquery


    【解决方案1】:

    你的相关性都是倒退的。正确的做法是:

    SELECT e.* 
    FROM empsalary e
    WHERE e.empsalary > (SELECT m.empsalary 
                         FROM empsalary  m
                         WHERE m.EmpID = e.ManagerID 
                        );
    

    请注意,我已将 m 表别名用于经理记录。这有助于遵循逻辑。

    【讨论】:

    • 技术上是对的,但你对相关性的逻辑解释对我来说还不够……谢谢。
    【解决方案2】:

    我不需要重新编写如何做到这一点,因为 Gordon 已经做得很好了,但我可以解释为什么你的返回 null...

    为了让我回答这个问题,我需要稍微重写你的,以帮助我阅读它。它与您的基本相同。此外,与 Gordon 所做的类似,我用 e 代替了 m,用 e1 代替了 e。我还将您的表称为 tblSalaries,因此表名与列名不同:

    SELECT * 
    FROM tblSalaries as m
    WHERE m.empsalary=(
                       SELECT e.empsalary 
                       FROM tblSalaries as e 
                       WHERE e.ManagerID = m.EmpID
                       AND e.EmpSalary > m e.EmpSalary)
    

    如果我们倒推并首先解释最后一部分:

    ...
    (
     SELECT e.empsalary 
     FROM tblSalaries as e 
     WHERE e.ManagerID = m.EmpID
     AND e.EmpSalary > m.EmpSalary)
    

    首先,WHERE m.ManagerID = e.EmpID 说“查找 e 中经理 ID 与 m 中员工 ID 相同的所有员工”。考虑到只有一个 managerID (6),那么 e 中的记录 1-5 都将匹配 m (6) 上的 manager 记录。

    你的下一个子句AND e.EmpSalary > m.EmpSalary 是寻找那些薪水高于经理的人。因此,按照您的预期,您将获得记录 5 (Roy)。

    现在回到你的主要查询:

    SELECT * 
        FROM tblSalaries as m
        WHERE m.empsalary= (...tblSalaries as e...)
    

    我们已经确定括号中的表 e 已经返回了 Roy,但我们也已经确定它只匹配表 m 中的记录,其中 m 是经理。最终,您要求找到经理的薪水 = 罗伊的薪水;答案是null

    【讨论】:

    • ,(5,'Roy',170000,6) ,(6,'Anvesh',168000,NULL) 他们的 ID 相等 (6=6) 和 170000>168000 并且我正在搜索这个 ID薪水,但结果为空,为什么我无法理解..
    • 是的,但他们的薪水不是——这就是您使用的“Where Clause”。使用您的别名,您的表 e 仅返回经理 (6,'Anvesh',168000,NULL),而表 e1 仅返回 Roy (5,'Roy',170000,6)。然后,您在这部分WHERE e.empsalary= 中要求选择所有经理的薪水 = 罗伊的薪水,即为空。尝试更改 Roy 的薪水以匹配经理的薪水。你会发现它把经理带回来了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    相关资源
    最近更新 更多