我不明白自我加入的必要性。有人可以向我解释一下吗?
一个简单的例子会很有帮助。
您可以将自联接视为两个相同的表。但是在规范化中,您不能创建表的两个副本,因此您只需模拟两个具有自联接的表。
假设您有两个表:
emp1
Id Name Boss_id
1 ABC 3
2 DEF 1
3 XYZ 2
emp2
Id Name Boss_id
1 ABC 3
2 DEF 1
3 XYZ 2
现在,如果您想获取每个员工的姓名及其老板的姓名:
select c1.Name , c2.Name As Boss
from emp1 c1
inner join emp2 c2 on c1.Boss_id = c2.Id
这将输出下表:
Name Boss
ABC XYZ
DEF ABC
XYZ DEF
当您有一个引用自身的表时,这很常见。示例:一个员工表,其中每个员工都可以有一个经理,并且您想要列出所有员工及其经理的姓名。
SELECT e.name, m.name
FROM employees e LEFT OUTER JOIN employees m
ON e.manager = m.id
自联接是表与自身的联接。
一个常见的用例是当表存储实体(记录)之间具有层次关系时。例如,一个包含个人信息(姓名、出生日期、地址...)的表格,并包括一列,其中包括父亲(和/或母亲)的 ID。然后用一个小查询
SELECT Child.ID, Child.Name, Child.PhoneNumber, Father.Name, Father.PhoneNumber
FROM myTableOfPersons As Child
LEFT OUTER JOIN myTableOfPersons As Father ON Child.FatherId = Father.ID
WHERE Child.City = 'Chicago' -- Or some other condition or none
我们可以在同一个查询中获取有关孩子和父亲(以及母亲,以及第二次自我加入等,甚至是祖父母等)的信息。
假设您有一张桌子users
,设置如下:
在这种情况下,如果您想在一个查询中同时提取用户信息和经理信息,您可以这样做:
SELECT users.user_id, users.user_name, managers.user_id AS manager_id, managers.user_name AS manager_name INNER JOIN users AS manager ON users.manager_id=manager.user_id
想象一个Employee
如下所述的表。所有员工都有一个经理,这也是一个员工(也许除了 CEO,其 manager_id 将为空)
Table (Employee):
int id,
varchar name,
int manager_id
然后,您可以使用以下选择来查找所有员工及其经理:
select e1.name, e2.name as ManagerName
from Employee e1, Employee e2 where
where e1.manager_id = e2.id
如果您的表是自引用的,它们会很有用。例如,对于一个页面表,每个页面可能有一个next
和previous
链接。这些将是同一个表中其他页面的 ID。如果在某个时候您想要获得三个连续页面,您将在具有相同表列的next
和列上执行两次自连接。previous
id
如果表无法引用自身,我们就必须为层次结构级别创建与层次结构中的层数一样多的表。但由于该功能可用,您将表连接到自身,sql 将其视为两个单独的表,因此所有内容都很好地存储在一个地方。
除了上面提到的答案(解释得很好)之外,我想添加一个示例,以便可以轻松地展示 Self Join 的使用。假设您有一个名为 CUSTOMERS 的表,它具有以下属性:CustomerID、CustomerName、ContactName、City、Country。现在你想列出所有来自“同一个城市”的人。您将不得不考虑该表的副本,以便我们可以在 CITY 的基础上加入它们。下面的查询将清楚地显示它的含义:
SELECT A.CustomerName AS CustomerName1, B.CustomerName AS CustomerName2,
A.City
FROM Customers A, Customers B
WHERE A.CustomerID <> B.CustomerID
AND A.City = B.City
ORDER BY A.City;
这里有很多正确的答案,但也有一个同样正确的变体。您可以将连接条件放在连接语句而不是 WHERE 子句中。
SELECT e1.emp_id AS 'Emp_ID'
, e1.emp_name AS 'Emp_Name'
, e2.emp_id AS 'Manager_ID'
, e2.emp_name AS 'Manager_Name'
FROM Employee e1 RIGHT JOIN Employee e2 ON e1.emp_id = e2.emp_id
请记住,有时您需要 e1.manager_id > e2.id
了解这两种情况的好处是有时您有大量的 WHERE 或 JOIN 条件,并且您希望将自连接条件放在另一个子句中以保持代码可读性。
没有人解决当员工没有经理时会发生什么。嗯?它们不包含在结果集中。如果您想包括没有经理但又不想返回错误组合的员工怎么办?
试试这只小狗;
SELECT e1.emp_id AS 'Emp_ID'
, e1.emp_name AS 'Emp_Name'
, e2.emp_id AS 'Manager_ID'
, e2.emp_name AS 'Manager_Name'
FROM Employee e1 LEFT JOIN Employee e2
ON e1.emp_id = e2.emp_id
AND e1.emp_name = e2.emp_name
AND e1.every_other_matching_column = e2.every_other_matching_column
一个用例是检查数据库中的重复记录。
SELECT A.Id FROM My_Bookings A, My_Bookings B
WHERE A.Name = B.Name
AND A.Date = B.Date
AND A.Id != B.Id
当您必须自行评估表的数据时,自连接很有用。这意味着它将关联同一张表中的行。
Syntax: SELECT * FROM TABLE t1, TABLE t2 WHERE t1.columnName = t2.columnName
例如,我们要查找 Initial Designation 等于当前指定的员工的姓名。我们可以通过以下方式使用自连接来解决这个问题。
SELECT NAME FROM Employee e1, Employee e2 WHERE e1.intialDesignationId = e2.currentDesignationId
它是链接列表/树的数据库等价物,其中一行包含对另一行的某种容量的引用。
这是外行术语自我加入的解释。自联接不是不同类型的联接。如果您了解其他类型的连接(内连接、外连接和交叉连接),那么自连接应该是直截了当的。在 INNER、OUTER 和 CROSS JOINS 中,您连接 2 个或更多不同的表。但是,在自联接中,您使用其加入同一个表。在这里,我们没有 2 个不同的表,而是使用表别名将同一个表视为不同的表。如果这仍然不清楚,我建议观看以下 youtube 视频。