关于SQL:左连接、右连接、外部连接和内部连接有什么区别?

What is the difference between Left, Right, Outer and Inner Joins?

我想知道如何区分所有这些不同的连接…


简单的例子:假设您有一个Students表和一个Lockers表。在SQL中,在联接中指定的第一个表Students是左表,而第二个表Lockers是右表。

每个学生可以被分配到一个储物柜,因此在Student表中有一个LockerNumber列。一个储物柜中可能有多个学生,但特别是在学年初,您可能会有一些没有储物柜的新生和一些没有分配学生的储物柜。

为了这个例子,假设你有100个学生,其中70个有储物柜。总共有50个储物柜,其中40个至少有1名学生,10个储物柜没有学生。

内部连接相当于"向我展示所有带储物柜的学生"。没有储物柜的学生或没有学生的储物柜都不见了。返回70行

左边的外部连接将是"给我看所有的学生,如果他们有相应的储物柜"。这可能是一个普通的学生名单,或者可以用来识别没有储物柜的学生。返回100行

右边的外部连接将是"显示所有储物柜,如果有分配给他们的学生"。这可以用来识别没有分配学生的储物柜,或者识别学生太多的储物柜。返回80行(40个储物柜中70个学生的列表,加上10个没有学生的储物柜)

完全外部连接将是愚蠢的,可能不会有太多的用处。类似于"向我展示所有学生和所有储物柜,并将它们匹配到您可以找到的地方",返回110行(所有100名学生,包括那些没有储物柜的学生)。加上10个没有学生的储物柜)

在这种情况下,交叉连接也相当愚蠢。它没有在学生表中使用链接的LockerNumber字段,因此您基本上会得到一个庞大的列表,列出每个可能的学生到储物柜的配对,不管它是否真的存在。返回5000行(100个学生x 50个储物柜)。将新学生与空储物柜进行匹配(通过过滤)可能很有用。


连接有三种基本类型:

  • INNERjoin比较两个表,只返回匹配的结果。当第一个表中的记录与第二个表中的多个结果匹配时,它们将被复制。内部联接往往会使结果集变小,但由于记录可以复制,这并不能保证。
  • CROSSjoin比较两个表,并返回两个表中所有可能的行组合。您可以从这种连接中获得很多甚至可能没有意义的结果,因此请谨慎使用。
  • OUTERjoin比较两个表,并在匹配可用时返回数据,否则返回空值。与内部联接类似,当一个表与另一个表中的多个记录匹配时,它将在一个表中复制行。外部联接往往会使结果集更大,因为它们本身不会从集中删除任何记录。还必须限定外部联接,以确定何时何地添加空值:
    • LEFT意味着无论什么都要保留第一个表中的所有记录,当第二个表不匹配时插入空值。
    • RIGHT的意思是相反的:无论什么都保留第二个表中的所有记录,如果第一个表不匹配,则插入空值。
    • FULL表示保留两个表中的所有记录,如果不匹配,则在两个表中插入一个空值。

您经常会看到语法中省略了OUTER关键字。相反,它将只是"左连接"、"右连接"或"完全连接"。这样做是因为内部联接和交叉联接对于左联接、右联接或全联接没有意义,因此它们本身就足够明确地指示外部联接。

下面是您可能希望何时使用每种类型的示例:

  • INNER:您要返回"发票"表中的所有记录及其对应的"发票行"。这假设每个有效发票至少有一行。
  • OUTER:您希望返回特定发票的所有"发票行"记录,以及相应的"库存项"记录。这是一个也销售服务的业务,这样不是所有的发票行都有一个IVentoryItem。
  • CROSS:您有一个数字表,有10行,每行保存值"0"到"9"。您希望创建一个日期范围表,以便在该范围内的每一天都有一条记录。通过重复地将这个表与它本身交叉连接,您可以根据需要创建任意多个连续整数(假设从10到1次幂开始,每个连接将指数加1)。然后使用date add()函数将这些值添加到范围的基准日期中。


只有4种:

  • 内部连接:最常见的类型。对于在联接条件下匹配的每对输入行,都会生成一个输出行。
  • 左外部联接:与内部联接相同,但如果在右侧表中找不到匹配行,则输出一行,其中包含左侧表中的值,右侧表中的每个值都使用NULL。这意味着左侧表中的每一行在输出中至少出现一次。
  • 右外部联接:与左外部联接相同,只是表的角色颠倒了。
  • 全外部联接:左、右外部联接的组合。两个表中的每一行将至少在输出中出现一次。
  • "交叉联接"或"笛卡尔联接"只是一个内部联接,没有为其指定联接条件,因此将输出所有行对。

    感谢Russelh指出了完整的连接,我忽略了这一点。


    SQL联接差异:

    很容易记住:

    INNER JOIN只显示两个表共用的记录。

    OUTER JOIN两个表的所有内容合并在一起,要么匹配要么不匹配。

    LEFT JOINLEFT OUTER JOIN相同(从第一个(最左边的)表中选择与右边表记录匹配的记录)。

    RIGHT JOINRIGHT OUTER JOIN相同(从第二个(最右端)表中选择与左表记录匹配的记录)。

    enter image description here


    在维基百科上查看join(sql)

    • 内部联接-给定两个表,内部联接返回两个表中存在的所有行
    • 左/右(外部)联接-给定的两个表返回联接的左或右表中存在的所有行,另外,当join子句匹配时,将返回另一侧的行,否则将为这些列返回空值。

    • 完全外部-给定的两个表返回所有行,当左列或右列不在时返回空值。

    • 交叉联接-笛卡尔联接,如果不小心使用,可能会很危险


    LEFT JOINRIGHT JOINOUTER JOIN的类型。

    INNER JOIN是默认值——两个表中的行必须与联接条件匹配。


    内部联接:仅显示来自两个表的数据时的行。

    外部联接:(左/右):显示左/右表中包含成对行的所有结果(如果存在或不存在)。


    让它更明显可能会有所帮助。一个例子:

    表1:

    学生姓名

    1
    2
    3
    4
    1               Raony
    2               Diogo
    3               Eduardo
    4               Luiz

    表2:

    学生储物柜

    1
    2
    3
    3               l1
    4               l2
    5               l3

    当我这样做的时候我得到了什么:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    -INNER JOIN OF TABLE 1 AND TABLE 2:

        - INNER JOIN RETURNS BOTH TABLES merged ONLY WHEN the KEY
          (ID_STUDENT) EXISTS IN BOTH TABLES

        ID_STUDENT       STUDENT_NAME      LOCKER  

            3               Eduardo          l1
            4               Luiz             l2

    -LEFT JOIN OF TABLE 1 AND TABLE 2:

        - LEFT JOIN merges BOTH TABLES WITH ALL records form TABLE 1, IN
          other words, there might be non-populated FIELDS FROM TABLE 2

        ID_ESTUDANTE    NOME_ESTUDANTE     LOCKER  

            1               Raony            -
            2               Diogo            -
            3               Eduardo          l1
            4               Luiz             l2

    -RIGHT JOIN OF TABLE 1 AND TABLE 2:

        - RIGHT JOIN merges BOTH TABLES WITH ALL records FROM TABLE 2, IN
          other words, there might be non-populated FIELDS FROM TABLE 1

        ID_STUDENT        STUDENT_NAME     LOCKER  

            3               Eduardo          l1
            4               Luiz             l2
            5               -                l3

    -Outter JOIN OF TABLE 1 AND TABLE 2:

        - RETURNS ALL records FROM BOTH TABLES, IN other words, there
          might be non-populated FIELDS either FROM TABLE 1 OR 2.

        ID_STUDENT        STUDENT_NAME     LOCKER  
            1               Raony            -
            2               Diogo            -
            3               Eduardo          l1
            4               Luiz             l2
            5               -                l3

    首先,您必须了解Join是做什么的?我们连接多个表并从连接的表中获得特定的结果。最简单的方法是交叉连接。

    假设表A有两列A和B,表B有三列C和D。如果我们应用交叉联接,它将产生许多无意义的行。然后我们必须使用主键进行匹配以获得实际数据。

    左:返回左表的所有记录和右表的匹配记录。

    右:它将返回到左连接的对面。它将返回右表中的所有记录和左表中的匹配记录。

    内景:这就像十字路口。它只返回两个表中匹配的记录。

    外部:这就像是联合。它将返回两个表中的所有可用记录。

    有时我们不需要所有的数据,而且我们只需要普通的数据或记录。我们可以使用这些连接方法很容易地得到它。记住,左连接和右连接也是外部连接。

    您可以使用交叉联接获取所有记录。但当涉及到数以百万计的记录时,它可能会很昂贵。因此,使用左、右、内或外联接使其简单化。

    谢谢