自我加入。内在,外在还是左都有问题?

时间:2017-06-29 02:13:02

标签: sql postgresql join self-join

我想知道这个,因为自联接只需要一个表,所以感觉它不会有所作为。 我读过这个问题:Explanation of self-joins。 有几个答案,他们使用不同类型的连接看似相同的任务。

它是否有所作为?如果是这样,你能举例说明一下吗?

4 个答案:

答案 0 :(得分:2)

这完全取决于您想要对数据做什么。 This回答很好地详细说明了自我内部联接的样子。我最近写了一份报告,要求比较学生连续两门课程的成绩。它是这样的:

给出一个表student_course

STUDENT_ID  COURSE  GRADE
1           MTH251  A
1           MTH252  B
2           MTH251  A
2           MTH252  A
3           MTH251  B
3           MTH252  C

查询:

SELECT course1.student_id
  , course1.course AS course1
  , course1.grade AS grade1
  , course2.course AS course2
  , course2.grade AS grade2
FROM student_course course1
INNER JOIN student_course course2
  ON course1.student_id = course2.student_id
WHERE course1.course = 'MTH251'
  AND course2.course = 'MTH252';

Fiddle here.对不起,PostgreSQL小提琴不适用于我,因此我使用Oracle进行测试。 PostgreSQL等价物应该看起来大致相同。

现在说我想看一个可能没有服用MTH252的学生。你可以这样做:

SELECT course1.student_id
  , course1.course AS course1
  , course1.grade AS grade1
  , course2.course AS course2
  , course2.grade AS grade2
FROM student_course course1
LEFT OUTER JOIN student_course course2
  ON course1.student_id = course2.student_id
  AND course2.course = 'MTH252'
WHERE course1.course = 'MTH251';

Other Fiddle

前者表示同时服用MTH251和MTH252的学生,后者表示已服用MTH251的学生,无论他们是否完成了MTH252。

正如Nick.McDermaid所指出的,自联接的工作方式与加入两个具有不同数据的表完全相同。

答案 1 :(得分:0)

确实有所作为。在概念上有很多方法可以考虑它 在某种程度上,连接意味着您希望使用一行而不是两行,如果可能的话。你基本上是拿两张桌子,然后用它们制作一张桌子。

我认为在内部,右/左和外部之间理解的最佳方式是表格

    **FULL Outer:**
name           number
john           
jamie          7
ann            10
              11
              12

有些行缺少元素,因为外连接使用每个表的每一个可能的行。在这种情况下,无论我们选择哪个链接器(即“ON”之后的内容),John的链接器值都与第二个表中的任何行都不对应。 11和12是第二个表中没有与其他名称中的名称匹配的链接器值的数字

内部意味着如果任何一个表的某个元素没有与另一个表共有的数据成员,那么我们必须跳过这些元素。因此表格变为

   **INNER**
    name      number
   jamie      7
    ann       10

如果从抽象的角度考虑它们,左/右连接是一回事,因为这些连接中的每一个都会导致其中一个表显示其完整的元素集,而另一个仅限于那些在另一个表中有一个伙伴。 左/右是外连接,但基本上只有半外连接。

    **left/right:**


   name           number
   lee
   john           
   jamie          7
   ann            10



   name           number           
   jamie          7
   ann            10
                  15
                  29

Explanation of self-joins 以他给出的内连接示例为例。但是,如果有些老板列出了员工表中找不到的员工,甚至列出了空值呢?如果员工在员工表中列出了老板,但老板表中没有老板,该怎么办?或者也许员工根本没有老板? (那个人实际上是现实的,因为有些人是自雇人士)

然后我们必须决定,我们究竟要查询的是什么?我们需要为自营职业的员工负责吗?如果是这样,则排除INNER JOIN。所以现在我们必须决定是否希望在数据库中包含没有员工的老板。

现实地思考,我可以想象我们会做左或右连接。

答案 2 :(得分:0)

首先,FlatStyleFlatApperance

确实有所不同,因为left joinouter join的定义在实现自联接时也是一样的。因此,假设您有一个典型的Employee表与经理。现在为了争论,我们可以说员工的经理之一不在员工名单中。因此,如果您进行典型的自我加入,您将无法获得该记录。但是在左连接的帮助下,您可以获得该记录。

inner join的另一个用途是使用where子句作为left join来查找left join表中但不在left表中的记录。您也可以为自联接实现相同的功能,而内部联接则无法实现。

以下是针对上述方案的一些查询,您可以看到使用right而不是where right_table.key is null可以执行的额外操作。

http://rextester.com/HICA42440

答案 3 :(得分:0)

LEFT(OUTER)JOIN ON定义给出INNER JOIN ON给出的行加左边的不匹配行,用NULL扩展。因此,如果每个左行匹配,则它们给出相同的答案。特别是如果ON条件是引用PK(主键)的左表的非NULL FK(外键)或另一个中的UNIQUE NOT NULL相等,那么每个左行都有匹配并且它们给出相同的答案。 RIGHT JOIN&正确的表格。

所以在LEFT self-JOIN中,如果每个左行都匹配,那么它们给出相同的答案。特别是如果ON条件是引用其PK(主键)的非NULL FK(外键)或其中的UNIQUE NOT NULL相等,则每行都有匹配,并且它们给出相同的答案。

例如,如果每个员工都有一位经理,那么EMPLOYEE(e,...,m)非 - NULL FOREIGN KEY (m) REFERENCES PK (e)LEFT自我 - JOIN ON left.m = right.e会得到与{INNER相同的结果1}}。

PS当你有一个假设时,你可以寻找可能恰好反驳它的反例。几乎任何小的随机值自我加入都会反驳你的。你试过吗?如果你有一种感觉"关于某些特殊情况的假设你可以再做一次。