自连接的说明

时间:2010-03-16 22:07:43

标签: sql self-join

我不了解自连接的必要性。有人可以向我解释一下吗?

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

13 个答案:

答案 0 :(得分:83)

您可以将自联接视为两个相同的表。但在规范化中,您无法创建表的两个副本,因此您只需模拟两个具有自连接的表。

假设您有两个表:

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

答案 1 :(得分:19)

当你有一个引用自己的表时,这很常见。示例:员工表,其中每个员工都可以拥有经理,并且您希望列出所有员工及其经理的姓名。

SELECT e.name, m.name
FROM employees e LEFT OUTER JOIN employees m
ON e.manager = m.id

答案 2 :(得分:17)

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

一个常见的用例是表存储实体(记录)之间具有层次关系的实体(记录)。例如,包含人员信息(姓名,DOB,地址......)并且包括其中包括父亲(和/或母亲)的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

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

答案 3 :(得分:5)

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

  • 用户ID
  • 用户名
  • 用户经理的身份证件

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

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

答案 4 :(得分:4)

如果您的表是自引用的,它们很有用。例如,对于页面表,每个页面可能有nextprevious链接。这些将是同一个表中其他页面的ID。如果您希望在某个时刻获得连续三页的页面,则可以在nextprevious列上使用相同的表id列进行两次自联接。

答案 5 :(得分:4)

想象一下名为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

答案 6 :(得分:4)

如果没有表引用自身的能力,我们必须为层次结构级别创建与层次结构中的层数一样多的表。但由于该功能可用,您将表连接到自身,并且sql将其视为两个单独的表,因此所有内容都可以很好地存储在一个位置。

答案 7 :(得分:4)

除了上面提到的答案(非常好解释)之外,我想添加一个例子,以便可以很容易地显示自我加入的使用。 假设您有一个名为CUSTOMERS的表,它具有以下属性: CustomerID,客户名称,联系人姓名,城市,国家/地区。 现在,您要列出所有来自同一城市的人员#34; 。 您将不得不考虑此表的副本,以便我们可以在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;

答案 8 :(得分:3)

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

答案 9 :(得分:1)

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

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

答案 10 :(得分:1)

当必须自己评估表的数据时,自连接很有用。这意味着它将关联同一表中的行。

Syntax: SELECT * FROM TABLE t1, TABLE t2 WHERE t1.columnName = t2.columnName

例如,我们要查找其初始名称等于当前名称的员工姓名。我们可以通过以下方式使用自连接解决此问题。

SELECT NAME FROM Employee e1, Employee e2 WHERE e1.intialDesignationId = e2.currentDesignationId

答案 11 :(得分:0)

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

答案 12 :(得分:-4)

这是以外行人的方式解释自我加入。自联接不是一种不同类型的联接。如果您已经了解其他类型的连接(内部,外部和交叉连接),那么自连接应该是直接的。在INNER,OUTER和CROSS JOINS中,您可以加入两个或更多不同的表。但是,在自联接中,您使用itslef加入相同的表。在这里,我们没有2个不同的表,但是使用表别名将同一个表视为不同的表。如果仍然不清楚,我建议您观看以下YouTube视频。

Self Join with an example

相关问题