自我联合的目的

时间:2017-04-19 17:10:22

标签: sql oracle

我正在学习使用SQL编程,并且刚刚介绍了自联接。我理解这些是如何工作的,但我不了解他们的目的是什么,除了非常具体的用法,加入员工表自己以整齐地展示员工和他们各自的经理。

可以使用下表证明此用法:

EmployeeID | Name          | ManagerID
    ------ | ------------- | ------
    1      | Sam           | 10
    2      | Harry         | 4
    4      | Manager       | NULL
   10      | AnotherManager| NULL

以下查询:

select worker.employeeID, worker.name, worker.managerID, manager.name
from employee worker join employee manager
on (worker.managerID = manager.employeeID);

哪会回来:

Sam   AnotherManager
Harry Manager

除此之外,还有其他任何情况下自我加入会有用吗?我无法弄清楚需要执行自联接的场景。

4 个答案:

答案 0 :(得分:3)

你的榜样很好。只要表包含外键,自联接就很有用。员工有经理,经理是......另一名员工。因此,自我联接在那里是有意义的。

许多层次结构和关系树非常适合这种情况。例如,您可能将父组织划分为区域,组,团队和办公室。其中每个都可以存储为“组织”,父ID为列。

或许您的公司有推荐计划,并且您想记录哪位客户推荐了某人。它们都是“客户”,在同一个表中,但其中一个与另一个有FK链接。

的层次结构非常适合这种情况,即实体可能具有多个“父”链接的层次结构。例如,假设您有facebook风格的数据记录每个用户和友情链接到其他用户。 可以适合此模型,但是对于用户拥有的每个朋友,您需要一个新的“用户”行,除了“relationshipUserID”之外,每一行都是重复的专栏或你称之为的任何内容。

在多对多关系中,您可能会有一个单独的“关系”表,其中包含“from”和“to”列,也可能是指示关系类型的列。

答案 1 :(得分:2)

我发现自联接在这种情况下最有用:

让所有与Sam一样为同一经理工作的员工。 (这不一定是分层的,这也可以是:让所有与Sam在同一地点工作的员工)

select e2.employeeID, e2.name
from employee e1 join employee e2
on (e1.managerID = e2.managerID)
where e1.name = 'Sam'

在表格中查找重复项也很有用,但效率非常低。

答案 2 :(得分:1)

这里有几个使用自联接的好例子。我经常使用的那个与"时间表"有关。我在教育方面使用时间表,但在其他情况下也是如此。

我使用自联接来确定两个项目是否相互冲突,例如学生可以安排两个课程同时进行,或者一个房间是双重预订。例如:

CREATE TABLE StudentEvents(
    StudentId int,
    EventId int,
    EventDate date,
    StartTime time,
    EndTime time
)

SELECT
    se1.StudentId,
    se1.EventDate,
    se1.EventId Event1Id,
    se1.StartTime as Event1Start,
    se1.EndTime as Event1End,
    se2.StartTime as Event2Start,
    se2.EndTime as Event2End,
FROM
    StudentEvents se1
    JOIN StudentEvents se2 ON
        se1.StudentId = se2.StudentId
        AND se1.EventDate = se2.EventDate
        AND se1.EventId > se2.EventId 
        --The above line prevents (a) an event being seen as clashing with itself
        --and (b) the same pair of events being returned twice, once as (A,B) and once as (B,A)
WHERE
    se1.StartTime < se2.EndTime AND
    se1.EndTime > se2.StartTime

类似的逻辑可用于在时间表数据中找到其他东西,例如可以从A到B到C的一对列车。

答案 3 :(得分:0)

只要您想要将同一个表的记录相互比较,自联接就很有用。示例包括:查找重复地址,查找交货地址与发票地址不同的客户,将每日报表中的总计(保存为记录)与前一天的总数进行比较等。