【问题标题】:What is the difference between Left, Right, Outer and Inner Joins? [duplicate]左、右、外连接和内连接有什么区别? [复制]
【发布时间】:2010-10-01 16:08:45
【问题描述】:

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

【问题讨论】:

  • 也取决于你的理解水平,对于像你这样的人来说,这篇文章除了对可能不完全理解的人来说什么都不会加入它很清楚
  • 这对我帮助很大...最简单的方法是制作测试表并与它们一起玩。 =P
  • The Coding Horror blog using Venn diagrams linked in the high upvoted 1st comment here被其作者后来在其cmets中否定。维恩图在讨论外连接和内连接时具有误导性和误用。在我在第一次评论中给出的重复链接中查看我的 cmets。

标签: sql database join


【解决方案1】:

只有4种:

  1. 内连接:最常见的类型。为在连接条件上匹配的每对输入行生成一个输出行。
  2. 左外连接:与内连接相同,不同之处在于如果右侧表中没有找到匹配行的任何行,则输出包含该表中的值的行在左侧,NULL 对应右侧表格中的每个值。这意味着左侧表格中的每一行将在输出中至少出现一次。
  3. 右外连接:与左外连接相同,只是表的角色颠倒了。
  4. 全外连接:左右外连接的组合。两个表中的每一行都会在输出中至少出现一次。

“交叉连接”或“笛卡尔连接”只是没有指定连接条件的内部连接,导致输出所有行对。

感谢 RusselH 指出 FULL 连接,我省略了。

【讨论】:

  • 全外连接和交叉连接(笛卡尔积)怎么样?
  • full 真的相当于两个外连接
  • FULL 是你搞砸内部连接时得到的结果,然后你在这里问一个问题“为什么我得到 N^2 行而不是 N”?然后每个人都会对你发火。
【解决方案2】:

LEFT JOINRIGHT JOINOUTER JOINs 的类型。

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

【讨论】:

  • 我无法相信这个答案怎么会有这么多的赞成票,同时又如此不完整。
  • 我认为这是对原始问题的更好回答。
【解决方案3】:

查看Join (SQL) on Wikipedia

  • 内连接 - 给定两个表,内连接返回两个表中存在的所有行
  • 左/右(外)连接 - 给定两个表返回存在于连接的左表或右表中的所有行,加上当连接子句匹配时将返回另一侧的行否则这些列将返回 null

  • Full Outer - 给定两个表返回所有行,当左列或右列不存在时将返回空值

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

【讨论】:

    【解决方案4】:

    简单示例:假设您有一个Students 表和一个Lockers 表。在 SQL 中,您在连接中指定的第一个表 StudentsLEFT 表,第二个表 LockersRIGHT 表。

    每个学生都可以分配到一个储物柜,所以Student 表中有一个LockerNumber 列。一个储物柜中可能有多个学生,但尤其是在学年开始时,您可能会有一些没有储物柜的新生和一些没有分配学生的储物柜。

    就本示例而言,假设您有 100 名学生,其中 70 名学生有储物柜。您总共有 50 个储物柜,其中 40 个储物柜至少有 1 个学生,10 个储物柜没有学生。

    INNER JOIN 相当于“告诉我所有带储物柜的学生”。
    任何没有储物柜的学生,或没有学生的任何储物柜都丢失了。
    返回 70 行

    LEFT OUTER JOIN 将是“向我展示所有学生,如果他们有相应的储物柜,请带上他们的储物柜”。
    这可能是一个普通的学生名单,或者可以用来识别没有储物柜的学生。
    返回 100 行

    RIGHT OUTER JOIN 将是“显示所有储物柜,以及分配给它们的学生(如果有的话)”。
    这可用于识别没有分配学生的储物柜,或有太多学生的储物柜。
    返回 80 行(40 个储物柜中的 70 名学生的列表,加上没有学生的 10 个储物柜)

    FULL OUTER JOIN 会很傻,可能没什么用处。
    类似“显示所有学生和所有储物柜,并在可以匹配的位置
    返回 110 行(所有 100 名学生,包括没有储物柜的学生。另外没有学生的 10 个储物柜)

    CROSS JOIN 在这种情况下也相当愚蠢。
    它不使用学生表中链接的lockernumber 字段,因此您基本上最终会得到一个包含所有可能的学生到-储物柜配对,无论它是否真的存在。
    返回 5000 行(100 个学生 x 50 个储物柜)。作为一个起点,将新学生与空储物柜匹配起来可能很有用(通过过滤)。

    【讨论】:

    • 使用您的示例,CROSS join 将作为创建储物柜分配的起点非常有用:从所有可能的组合开始,然后使用其他条件从列表中过滤结果。
    • 不错的答案。我相信当您需要大量记录时,Cross Join 最常用于从几行生成测试数据。
    • FULL OUTER JOINS 在搜索孤立数据或比较同一数据集的不同版本时非常有用。
    • 交叉加入又名笛卡尔积
    • 我认为您开始查询的方式会影响连接类型的结果。例如,SELECT * FROM students RIGHT OUTER JOIN lockers... 将产生与SELECT * FROM lockers RIGHT OUTER JOIN students... 不同的结果。很好的答案,但希望看到它更新完整的SQL 查询
    【解决方案5】:

    有三种基本的连接类型:

    • INNER join 比较两个表,只返回匹配的结果。当第一个表中的记录与第二个表中的多个结果匹配时,它们会重复。 INNER 联接往往会使结果集更小,但由于记录可以重复,因此不能保证这一点。
    • CROSS join 比较两个表并返回两个表中所有可能的行组合。您可以从这种连接中获得很多甚至可能没有意义的结果,因此请谨慎使用。
    • OUTER join 比较两个表并在匹配可用时返回数据,否则返回 NULL 值。与 INNER 连接一样,当它匹配另一张表中的多条记录时,这将复制一张表中的行。 OUTER 联接倾向于使结果集更大,因为它们本身不会从集中删除任何记录。您还必须限定 OUTER 连接以确定何时何地添加 NULL 值:
      • LEFT 表示无论如何保留第一个表中的所有记录,并在第二个表不匹配时插入 NULL 值。
      • RIGHT 表示相反的意思:无论如何保留第二张表中的所有记录,并在第一张表不匹配时插入 NULL 值。
      • FULL 表示保留两个表中的所有记录,如果不匹配,则在任一表中插入 NULL 值。

    您经常会看到语法中省略了OUTER 关键字。相反,它将只是“LEFT JOIN”、“RIGHT JOIN”或“FULL JOIN”。这样做是因为 INNER 和 CROSS 连接对于 LEFT、RIGHT 或 FULL 没有任何意义,因此它们本身就足以明确指示 OUTER 连接。

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

    • INNER:您希望从“Invoice”表中返回所有记录,以及它们对应的“InvoiceLines”。这假定每张有效的发票都至少有一行。
    • OUTER:您想要返回特定发票的所有“InvoiceLines”记录,以及它们对应的“InventoryItem”记录。这是一家还销售服务的企业,因此并非所有 InvoiceLines 都有 IventoryItem。
    • CROSS:您有一个包含 10 行的数字表,每行包含值 '0' 到 '9'。您想创建一个日期范围表来加入,以便在该范围内的每一天都有一条记录。通过重复将此表与自身交叉连接,您可以根据需要创建任意数量的连续整数(假设您从 10 的 1 次方开始,每个连接都会将 1 添加到指数)。然后使用 DATEADD() 函数将这些值添加到该范围的基准日期。

    【讨论】:

    • 不错。如果你只写“JOIN”,我只会添加它,这意味着 INNER JOIN。
    【解决方案6】:

    内连接:只显示行,当它有来自两个表的数据时。

    外连接(左/右):显示左/右表的所有结果与配对行(s),如果它存在

    【讨论】:

      【解决方案7】:

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

      表 1:

      ID_STUDENT STUDENT_NAME

      1               Raony
      2               Diogo
      3               Eduardo
      4               Luiz
      

      表 2:

      ID_STUDENT 储物柜

      3               l1
      4               l2
      5               l3
      

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

      -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
      

      【讨论】:

        【解决方案8】:

        首先你要明白join是做什么的?我们连接多个表并从连接的表中获取特定结果。最简单的方法是cross join

        假设 tableA 有两列 A 和 B。而 tableB 有三列 C 和 D。 如果我们应用交叉连接,它会产生很多无意义的行。然后我们必须使用主键进行匹配才能获取实际数据。

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

        右:它将与左连接相反。它将返回右表中的所有记录和左表中的匹配记录。

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

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

        有时我们不需要所有数据,而且我们应该只需要常用数据或记录。我们可以使用这些连接方法轻松获得它。记住左右连接也是外连接。

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

        谢谢

        【讨论】:

          【解决方案9】:

          SQL JOINS 区别:

          很容易记住:

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

          OUTER JOIN两个表的所有内容无论是否匹配都会合并在一起。

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

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

          【讨论】:

          • 有一种正确且相关的方式来标记维恩图圈,但这不是。圆圈不是输入表。结果行也不是输入行,因此您的描述在那里是错误的。这也不清楚——你没有解释“两者共同”、“匹配”、“合并”。
          猜你喜欢
          • 2017-02-26
          • 2011-02-12
          • 2011-05-23
          • 2013-08-25
          • 1970-01-01
          • 1970-01-01
          • 2015-01-11
          • 2011-04-22
          相关资源
          最近更新 更多