了解自联接中 ON 子句的顺序 (SQL)

Understanding Order of ON Clause in Self-Joins (SQL)

我正在尝试了解 SQL 自连接 - 特别是 ON 子句的顺序在查询中的重要性。这可能是一个基本问题,但请耐心等待,因为我是查询语言的初学者。

这实际上是一个 LeetCode Question - #181,我试图找到薪水高于其经理的员工。您可以通过 LeetCode link 或我在下面提供的 SQL Fiddle 示例来检查架构。

问题:

基本上,当我 运行 以下两个查询时,我试图了解输出的差异:

我更改了 ON 子句的顺序 From (ON e.ManagerId = m.Id) 到 (ON m.ManagerId = e.Id) 并且我从所需的输出中得到相反的答案。我认为因为它是自连接,所以顺序无关紧要,因为我是从相同的 table 中提取信息。

请让我知道我遗漏了什么,并尽可能指出任何方向! 提前致谢!

1) 正确查询以获得所需的输出

Select *
FROM Employee e
INNER JOIN Employee m
ON e.ManagerId = m.Id
WHERE e.Salary > m.Salary

SQL Fiddle Example

2) 查询不正确

Select *
FROM Employee e
INNER JOIN Employee m
ON m.ManagerId = e.Id
WHERE e.Salary > m.Salary

SQL Fiddle Example

在这两个查询中,您都将一名员工与另一名员工联系在一起。然而,在第一个查询中,您调用了下属 e 和经理 m,而在第二个查询中,您调用了经理 e 和下属 m。让我们更仔细地看一下:

Select *
FROM Employee e
INNER JOIN Employee m
ON e.ManagerId = m.Id
WHERE e.Salary > m.Salary

您正在将一名员工(您简称为 e)与其经理(此处称为 m 的员工,其 ID 在员工记录中作为经理 ID 引用)合并。然后你只保留员工工资高于经理的员工/经理对。

Select *
FROM Employee e
INNER JOIN Employee m
ON m.ManagerId = e.Id
WHERE e.Salary > m.Salary

你正在合并一个员工(你简称为e)和他的下属(这里叫m的员工,其经理ID引用员工记录)。因此,您称为 e 的员工是其他员工的经理。然后你只保留经理的薪水大于下属的员工(经理)/下属对。

功能上顺序无关紧要(因此,'ON e.ManagerId = m.Id' 与 'ON m.Id = e.ManagerId' 相同)。

你在这里做的是加入不同的列,代表不同的东西。

在错误的查询中,您说的是 "the managers managerID is the same as the employees ID",这不是真的。经理(正如您在 table 中看到的那样)本身没有经理。

您实际上所做的是反向连接。如果您要在 where 语句中交换符号,那么 WHERE e.Salary > m.SalaryWHERE e.Salary < m.Salary 您会得到与正确查询相同的答案

我认为您没有意识到 table aliases 指的是人。 table 的 m 副本是经理,因此变量 m.managerId 将引用经理的经理。这不是你想要的。所以正确的 link:

e.ManagerId = m.Id

正在link将员工行的经理转换为经理行的 ID。

您可能想将其视为只有 Manager_id 列中的 ID 是经理。

所以要获得他们的名字,您可以这样做:

select name from Employee where id in (select distinct ManagerId from Employee)

  • distinct 是可选的。如果我正在取消嵌套 select,我会倾向于这样做,因为只在其中看到一次相同的 ManagerId 是有意义的。两名以上的员工可能拥有同一位经理。

尝试 运行 不带 where 子句的查询,您会看到相同的结果,但列顺序已切换。这是因为 ON 子句:

  • ON e.ManagerId = m.Id

    (员工e到经理m)

    或者手写加入 Employee ManagerId,到 Manager Id

    Joe 作为员工,Sam 作为经理(升序层次结构 作为你跨列阅读)

  • ON m.ManagerId = e.Id

    (经理 m 到员工 e)

    或者手写加入经理ManagerId,到员工Id

    Sam 作为经理,Joe 作为员工(降序层次结构 作为你跨列阅读)

列顺序不受约束,如果你将 WHERE 子句从 > 翻转到 <=,当你翻转 ON 前缀顺序时,你会产生相同的结果结果。