我们什么时候需要自我加入?

时间:2015-05-13 16:43:54

标签: sql

我是SQL新手。我只知道基本的查询但不深入。我搜索了必要的自我加入,我找到了this question

大部分答案都说它对引用同一个表很有用。

示例查询是:

Select e1.employeeName
     from employee e1, employee e2
     where e1.employeeid = e2.supervisorid;

使用

我们不能得到相同的结果
select employeeName
       from employee
       where employeeid = supervisorid;

或者是自我加入但写作方式不同?如果我理解错误,请告诉我。

6 个答案:

答案 0 :(得分:1)

select employeeName
from employee
where employeeid = supervisorid;

会告诉您作为自己主管的员工的姓名。哪个不行。另一个查询实际应该是

Select e1.employeeName as employee, e2.employeeName as supervisor
from employee e1
left join employee e2 on e1.supervisorid = e2.employeeid;

获得两个名称,员工和主管之一。

答案 1 :(得分:1)

在您链接的示例中,相关表包含对自身的引用。对于该特定示例,它是一份员工列表,其中一些员工是其他员工的主管。由于有一个表,而不是主管表和非主管表,因此非主管使用自联接来引用行中的主管。

如果员工是他们自己的主管,您的第二个查询将仅返回结果。

答案 2 :(得分:1)

自联接的定义是一个连接到自身的表。 第一个查询有拼写错误。它应该是

Select e1.employeeName
     from employee e1, employee e2
     where e1.employeeid = e2.supervisorid;

注意where子句中的e2。 更正后,第一个查询将为您提供每个监督员工的姓名。

第二个查询将为您提供每位员工的姓名,他们是自己的主管。可能是一个空集。

为了帮助您理解它,请查看以下示例:

table employee

employeeId supervisorId employeeName
1          null         Big Boss
2          2            Medium Boss
3          3            Worker Bee

select e1.employeeName, e2.employeeName
     from employee e1, employee e2
     where e1.employeeid = e2.supervisorid;

将返回:

 Medium Boss Big Boss
 Worker Bee  Medium Boss

您可以制作一个类似的解决方案,使用2个表,一个用于员工,一个用于主管。

Table employee
employeeId employeeName SupervisorId
1          Big Boss     null
2          Medium Boss  1
3          Worker Bee   2

table supervisors
supervisorId supervisorName
1            Big Boss
2            Medium Boss

并将您的查询写为:

Select e.employeeName, s.supervisorName 
   from supervisors s, employees e
   where s.supervisorId = e.supervisorId

也将返回:

 Medium Boss Big Boss
 Worker Bee  Medium Boss

但是你会复制主管的员工数据,因为他们大多数都是员工。

答案 3 :(得分:0)

您的第二个查询只会返回员工是他自己的主管的结果。 而对于第一个,它将员工表与自己联系起来,以获得他的主管ID。

另一个自我加入真正派上用场的地方就是当你想要加入一个带有日期列的记录并检查后续行是否具有相同的值时。

编辑 - 回答评论中的问题

所以,例如你有像

这样的记录
ValueCol DateCol
25       '12/31/2014'
25       '1/1/2015'
30       '1/2/2015'

您的自我加入将如下所示:

Select t1.ValueCol, t2.ValueCol 
from t1
INNER JOIN t2 
ON t1.DateCol = DATEADD(DAY,1,t2.DateCol)

结果将是:

25   25
25   30

这可以帮助您检查同一个表中日期和上一个日期之间的ValueCol的相等性。

如果可以解释,请告诉我。

答案 4 :(得分:0)

以不同的方式思考!

而不是"表",思考"设置",您在SQL中的生活将变得更加容易。因此,在这种情况下,您可以查看此表"表"作为一组不同的集合,您可以使用谓词定义它们。

因此,如果您有员工表,则一组是所有员工。另一组可以是这些员工的主管。 JOIN子句可帮助您定义第二组的检索条件,如果需要,还可以在WHERE子句中添加更多条件。

这是第1组(所有员工):

SELECT
  e.employeeId,
  e.employeeName,
  e.supervisorId
FROM
  employee e

这是第2组(所有主管):

SELECT
  e.employeeId,
  e.employeeName
FROM
  employee e
WHERE
  e.employeeId IN
  (
  SELECT DISTINCT supervisorId FROM employee WHERE supervisorId IS NOT NULL
  )

您的SELECT查询的输出是一个新的集合(或者#34;表",如果您愿意),它将主管设置为员工集合,以便将主管与员工相关联,从而创建一个新的集合,由一个具有更多属性的新定义的元组组成。

您可以将这些视为"表",并相应地加入它们:

SELECT
  emp.employeeId,
  emp.employeeName,
  emp.supervisorId,
  sup.employeeName supervisorName
FROM
  (
    SELECT
      e.employeeId,
      e.employeeName,
      e.supervisorId
    FROM
      employee e
  ) emp
  INNER JOIN
  (
    SELECT
      e.employeeId,
      e.employeeName
    FROM
      employee e
    WHERE
      e.employeeId IN
      (
      SELECT DISTINCT supervisorId FROM employee WHERE supervisorId IS NOT NULL
      )
  ) sup ON
    sup.employeeId = emp.supervisorId

您现在可以看到我们如何创建2"表" (套)在飞行中,并加入他们。然而,这个人为的例子是不必要的复杂。我们可以这样做:

SELECT
  emp.employeeId,
  emp.employeeName,
  emp.supervisorId,
  sup.employeeName supervisorName
FROM
  employee emp
  INNER JOIN employee sup ON
    sup.employeeId = emp.supervisorId

这实现了同样的目的,即基于一组雇员元组和另一组雇员元组之间的JOIN定义一个新集合。请注意,此新集也可用作"表"。这只是你的想法问题。

请参阅此资源以获取更多可视化:

Visual Representation of SQL Joins

答案 5 :(得分:0)

当您在同一张桌子中有父子关系时。然后你应该使用自我加入。

喜欢何时找到经理和员工,菜单和子菜单,appversion和颠覆。我们通常将这种类型的数据存储在一个表中。要查询这个,我们必须使用自联接。