自我加入相关子查询

时间:2018-01-28 19:45:39

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

我需要找一个薪水高于经理的员工。为此,我习惯了以下查询并且它有效;


    SELECT 
        e1.EmpID
        ,e1.EmpName
        ,e1.EmpSalary
        ,e1.ManagerID
    FROM empsalary e
    INNER JOIN empsalary e1 ON e.EmpID = e1.ManagerID
    WHERE 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)

2 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:0)

由于戈登已经做了足够好的工作,所以我没有必要重新编写如何做到这一点,但我可以解释为什么你的回报为空...

我要回答这个问题,我需要稍微重写一下,以帮助我阅读。它与你的基本相同。此外,与戈登的表现类似,我用e代替m,e代替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.EmpI D说'查找e中所有员工的经理ID与m'中的员工ID相同。考虑到只有一个managerID(6),那么来自e的记录1-5将匹配经理记录,在m(6)上。

您的下一个条款AND e.EmpSalary > m.EmpSalary是找到那些薪水高于经理人的人。因此,您可以按照自己的意愿留下记录5(Roy)。

现在返回主查询:

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

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