了解自联接中 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
2) 查询不正确
Select *
FROM Employee e
INNER JOIN Employee m
ON m.ManagerId = e.Id
WHERE e.Salary > m.Salary
在这两个查询中,您都将一名员工与另一名员工联系在一起。然而,在第一个查询中,您调用了下属 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.Salary
到 WHERE 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
前缀顺序时,你会产生相同的结果结果。
我正在尝试了解 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
2) 查询不正确
Select *
FROM Employee e
INNER JOIN Employee m
ON m.ManagerId = e.Id
WHERE e.Salary > m.Salary
在这两个查询中,您都将一名员工与另一名员工联系在一起。然而,在第一个查询中,您调用了下属 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.Salary
到 WHERE 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
前缀顺序时,你会产生相同的结果结果。