自我连接的解释

我不明白需要自我join。 有人可以向我解释吗?

一个简单的例子将是非常有帮助的。

您可以将自连接视为两个相同的表。 但是在标准化中,你不能创build表的两个副本,所以你只需要模拟有两个自联接的表。

假设你有两个表:

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 

自连接是表与自身的连接。

一个常见的用例是当表存储实体(logging)时,它们之间有层次关系 。 例如,包含人员信息(姓名,出生date,地址…)并包括包含父亲(和/或母亲)的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 

我们可以在同一个查询中获得有关孩子和父亲(以及母亲,第二次自我join等,甚至是父母等)的信息。

假设你有一个表users ,设置如下:

  • 用户名
  • 用户名
  • 用户经理的ID

在这种情况下,如果要在一个查询中提取用户信息pipe理员信息,可以这样做:

 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 

如果没有表引用自己的能力,我们将不得不为层次结构层数创build层次结构级别的表。 但是由于这个function是可用的,所以你将表连接到自己,sql将它视为两个单独的表,所以一切都很好地存储在一个地方。

如果你的表是自引用的,它们是有用的。 例如,对于一个页面的表格,每个页面可能有一个nextprevious链接。 这些将是同一个表中其他页面的ID。 如果在某一时刻想要获得连续页面的三倍,则可以使用同一个表的id列对next列和previous列进行两次自连接。

想象下面描述的一个叫Employee的表。 所有员工都有一个经理,也是一名员工(也许除了首席执行官,其manager_id将为空)

 Table (Employee): int id, varchar name, int manager_id 

然后,您可以使用以下select来查找所有员工及其经理:

 select e1.name, e2.name as ManagerName from Employee e1, Employee e2 where where e1.manager_id = e2.id 

这里有很多正确的答案,但有一个变化是同样正确的。 您可以将连接条件放在连接语句中,而不是在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 

一个用例是检查数据库中的重复logging。

 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 

除了上面提到的答案(其中有很好的解释)之外,我想添加一个例子,这样就可以很容易地显示自我join的使用。 假设您有一个名为CUSTOMERS的表,它具有以下属性:CustomerID,CustomerName,ContactName,City,Country。 现在你想列出所有来自“同一城市”的人。 你将不得不考虑这个表的副本,以便我们可以在CITY的基础上join他们。 下面的查询将清楚地显示它的含义:

 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; 

它是链接列表/树的数据库等价物,其中一行包含某行到另一行的引用。

这是以非道德的方式来expression自我的join。 自连接不是一种不同types的连接。 如果你已经理解了其他types的连接(内连接,外连接和交叉连接),那么自连接应该是直接的。 在INNER,OUTER和CROSS JOINS中,您可以join2个或更多不同的表格。 但是,在自我join中,您可以使用itslefjoin同一张表。 在这里,我们没有2个不同的表,但是使用表别名将同一个表视为不同的表。 如果这仍然不清楚,我会build议观看以下YouTubevideo。

自我join一个例子