代码之家  ›  专栏  ›  技术社区  ›  Chris de Vries

“内部联接”和“外部联接”有什么区别?

  •  4210
  • Chris de Vries  · 技术社区  · 16 年前

    又如何 LEFT JOIN , RIGHT JOIN FULL JOIN 适应?

    27 回复  |  直到 6 年前
        1
  •  5651
  •   Darryl Hein IrishChieftain    7 年前

    假设您连接的列没有重复项,这是非常常见的情况:

    • A和B的内部连接给出了相交B的结果,即A的内部部分 Venn diagram 交叉。

    • A和B的外部连接给出了联合B的结果,即维恩图联合的外部部分。

    实例

    假设您有两个表,每个表只有一列,数据如下:

    A    B
    -    -
    1    3
    2    4
    3    5
    4    6
    

    请注意,(1,2)对于A是唯一的,(3,4)对于B是唯一的,(5,6)对于B是唯一的。

    内连接

    使用任意一个等价查询的内部联接提供两个表的交集,即它们有共同的两行。

    select * from a INNER JOIN b on a.a = b.b;
    select a.*, b.*  from a,b where a.a = b.b;
    
    a | b
    --+--
    3 | 3
    4 | 4
    

    左外连接

    左外部联接将给出A中的所有行,以及B中的任何公共行。

    select * from a LEFT OUTER JOIN b on a.a = b.b;
    select a.*, b.*  from a,b where a.a = b.b(+);
    
    a |  b
    --+-----
    1 | null
    2 | null
    3 |    3
    4 |    4
    

    右外部联接

    右外部联接将给出B中的所有行,以及A中的任何公共行。

    select * from a RIGHT OUTER JOIN b on a.a = b.b;
    select a.*, b.*  from a,b where a.a(+) = b.b;
    
    a    |  b
    -----+----
    3    |  3
    4    |  4
    null |  5
    null |  6
    

    全外部连接

    一个完整的外部连接将为您提供A和B的联合,即A中的所有行和B中的所有行。如果A中的某些内容在B中没有相应的数据,那么B部分为空,反之亦然。

    select * from a FULL OUTER JOIN b on a.a = b.b;
    
     a   |  b
    -----+-----
       1 | null
       2 | null
       3 |    3
       4 |    4
    null |    6
    null |    5
    
        2
  •  2532
  •   Michel Ayres user1485518    10 年前

    此外,您还可以为不同的连接类型考虑以下模式;

    visual explanation of joins

    来源: Visual-Representation-of-SQL-Joins 详细解释: C.L. Moffatt

        3
  •  604
  •   Martin Smith    9 年前

    我推荐 Jeff's blog article . 我所见过的最好的描述,加上有一个可视化,例如:

    内部连接:

    enter image description here

    完全外部联接:

    enter image description here

        4
  •  576
  •   Konsta Peltoniemi Martin Smith    6 年前

    维恩图并不是真的适合我。

    例如,它们不显示交叉联接和内部联接之间的任何区别,或者更一般地显示不同类型的联接谓词之间的任何区别,或者提供一个关于它们将如何操作的推理框架。

    理解逻辑处理是不可替代的,不管怎样,它都比较容易掌握。

    1. 想象一个交叉连接。
    2. 评价 on 对步骤1中的所有行执行子句,保留谓词计算结果为的行 true
    3. (仅用于外部联接)在步骤2中丢失的任何外部行中重新添加。

    (注意:在实践中,查询优化程序可能会找到比上述纯逻辑描述更有效的执行查询的方法,但最终结果必须相同)

    我将从一个动画版本的 全外部连接 . 下面是进一步的解释。

    enter image description here


    解释

    源表

    enter link description here

    先从A开始 CROSS JOIN (又称笛卡尔积)。这个没有 ON 子句,只返回两个表中的每一行组合。

    从交叉连接中选择A.颜色,B.颜色

    enter link description here

    内部和外部联接有一个“on”子句谓词。

    • 内部连接。 为交叉联接结果中的所有行计算“on”子句中的条件。如果为真,则返回联接的行。否则丢弃它。
    • 左外部连接。 对于左表中不匹配任何内容的任何行,与inner join相同。使用右表列的空值输出这些内容。
    • 右外部连接。 对于右表中不匹配任何内容的任何行,与内部联接相同。将这些行与左表列的空值输出。
    • 完全外部联接。 与内部联接相同,然后按照左外部联接保留左不匹配行,按照右外部联接保留右不匹配行。

    一些实例

    从内部连接中选择A.颜色,B.颜色A.颜色=B.颜色

    上面是典型的equi连接。

    Inner Join

    动画版本

    enter image description here

    从内部连接中选择A.颜色,B.颜色A.颜色不在(‘绿色’、‘蓝色’)

    内部联接条件不必是相等条件,也不需要引用来自两个表(甚至其中一个表)的列。评价 A.Colour NOT IN ('Green','Blue') 在交叉联接的每一行返回。

    inner 2

    从1=1的内部连接B中选择A.颜色,B.颜色

    对于交叉联接结果中的所有行,联接条件的计算结果都为true,因此这与交叉联接相同。我不会再重复16行的图片了。

    从左侧外部连接处选择A.颜色,B.颜色A.颜色=B.颜色

    外部联接的逻辑计算方式与内部联接相同,但如果左表中的一行(对于左联接)根本不与右表中的任何行联接,则在结果中保留 NULL 右侧列的值。

    LOJ

    从左侧外部连接处选择A.颜色,B.颜色,A.颜色=B.颜色,其中B.颜色为空

    这只会将前一个结果限制为只返回 B.Colour IS NULL . 在这种特殊情况下,这些行将是保留的行,因为它们在右侧表中不匹配,查询将返回在表中不匹配的单个红色行。 B . 这就是所谓的反半连接。

    IS NULL 不可为空或联接条件确保 无效的 值将被排除在外,以便此模式正常工作,并避免只返回恰好具有 无效的 该列的值以及不匹配的行。

    loj is null

    从右侧外部连接处选择A.颜色,B.颜色A.颜色=B.颜色

    右外部联接的作用类似于左外部联接,但它们保留右表中不匹配的行,空扩展左列。

    ROJ

    从一个完整的外部连接中选择A.颜色,B.颜色,A.颜色=B.颜色

    完全外部联接结合了左联接和右联接的行为,并保留左表和右表中不匹配的行。

    FOJ

    从1=0的完整外部连接B中选择A.颜色,B.颜色

    交叉联接中没有与 1=0 谓语。两边的所有行都使用正常的外部联接规则来保存,而另一边的表中的列为空。

    FOJ 2

    从1=0的完整外部连接B中选择“合并”(a.colour,b.colour)作为颜色。

    通过对前面的查询进行细微的修改,可以模拟 UNION ALL 两张桌子中的一张。

    UNION ALL

    从左侧外部连接B中选择A.颜色,B.颜色A.颜色=B.颜色,其中B.颜色=绿色

    请注意 WHERE 子句(如果存在)在联接之后逻辑地运行。一个常见的错误是执行左外部联接,然后在右表上包含一个条件为的WHERE子句,该条件最终排除不匹配的行。最后执行外部连接…

    LOJ

    …然后是“where”子句。 NULL= 'Green' 不计算为true,因此外部联接保留的行最终会被丢弃(与蓝色联接一起),从而有效地将联接转换回内部联接。

    LOJtoInner

    如果只包含b中颜色为绿色的行和a中的所有行,不管正确的语法是什么

    在A.colour=B.colour和B.colour='green'上从左侧外部连接B中选择A.colour、B.colour

    enter image description here

    SQL小提琴

    请参阅这些示例 run live at SQLFiddle.com .

        5
  •  127
  •   ajitksharma    6 年前

    联接 用于组合来自两个表的数据,结果是一个新的临时表。连接是基于一个叫做谓词的东西来执行的,它指定了执行连接时要使用的条件。内部联接和外部联接的区别在于,内部联接只返回基于联接谓词实际匹配的行。 让我们考虑雇员和位置表:

    enter image description here

    内部连接: 内部联接通过组合两个表的列值来创建新的结果表( 员工 位置 )基于连接谓词。查询比较 员工 每行 位置 查找满足联接谓词的所有行对。当通过匹配非空值满足联接谓词时,每个匹配行对的列值 员工 位置 合并为结果行。 下面是内部联接的SQL将是什么样子的:

    select  * from employee inner join location on employee.empID = location.empID
    OR
    select  * from employee, location where employee.empID = location.empID
    

    下面是运行该SQL的结果: enter image description here enter image description here

    外部连接: 外部联接不需要两个联接表中的每个记录都有匹配的记录。联接的表保留每个记录,即使不存在其他匹配的记录。外部联接进一步细分为左外部联接和右外部联接,具体取决于保留的表行(左或右)。

    左外部连接: 表的左外部联接(或简单的左联接)的结果 员工 位置 始终包含“左”表的所有记录( 员工 ,即使联接条件在“right”表中找不到任何匹配的记录。( 位置 ) 下面是左外部联接的SQL,使用上面的表:

    select  * from employee left outer join location on employee.empID = location.empID;
    //Use of outer keyword is optional
    

    现在,运行此SQL的结果如下: enter image description here enter image description here

    右外部连接: 右外部联接(或右联接)与左外部联接非常相似,除非对表进行相反的处理。“右”表中的每一行( 位置 )将至少出现在联接表中一次。如果“左”表中没有匹配的行( 员工 )存在,空值将出现在来自的列中 员工 对于那些没有匹配的记录 位置 . 这就是SQL的样子:

    select * from employee right outer join location  on employee.empID = location.empID;
    //Use of outer keyword is optional
    

    使用上面的表,我们可以显示右外部联接的结果集是什么样子的:

    enter image description here enter image description here

    全外部连接: 完全外部联接或完全联接是通过在联接的结果中包含不匹配的行来保留不匹配的信息,请使用完全外部联接。它包括两个表中的所有行,不管另一个表是否具有匹配的值。 enter image description here

    Image Source

    MySQL 8.0 Reference Manual - Join Syntax

    Oracle Join operations

        6
  •  118
  •   Peter Mortensen icecrime    10 年前

    内连接

    只检索匹配的行,即, A intersect B .

    Enter image description here

    SELECT *
    FROM dbo.Students S
    INNER JOIN dbo.Advisors A
        ON S.Advisor_ID = A.Advisor_ID
    

    左外连接

    从第一个表中选择所有记录,在第二个表中选择任何记录 与联接键匹配的表。

    Enter image description here

    SELECT *
    FROM dbo.Students S
    LEFT JOIN dbo.Advisors A
        ON S.Advisor_ID = A.Advisor_ID
    

    全外部连接

    从第二个表中选择所有记录,并选择第一个表中的所有记录 与联接键匹配的表。

    Enter image description here

    SELECT *
    FROM dbo.Students S
    FULL JOIN dbo.Advisors A
        ON S.Advisor_ID = A.Advisor_ID
    

    工具书类

        7
  •  104
  •   Peter Mortensen icecrime    10 年前

    简单来说:

    内连接 仅检索匹配的行。

    而一个 外部连接 从一个表中检索匹配的行,并从另一个表中检索所有行……结果取决于所使用的行:

    • :右表中的匹配行和左表中的所有行

    • 对吗? :左表中的匹配行和右表中的所有行或

    • :所有表中的所有行。有没有火柴没关系

        8
  •  96
  •   1800 INFORMATION    10 年前

    只有在联接的另一侧(右侧)有匹配记录时,内部联接才会显示行。

    (左)外部联接在左侧显示每条记录的行,即使联接的另一侧(右)上没有匹配的行。如果没有匹配的行,则另一侧(右侧)的列将显示空值。

        9
  •  71
  •   SergeyUr    6 年前

    内部联接要求联接表中存在具有相关ID的记录。

    外部联接将返回左侧的记录,即使右侧不存在任何记录。

    例如,您有一个orders和一个orderdetails表。它们通过“orderID”关联。

    命令

    • 订单编号
    • 客户名称

    订单详情

    • 有序细节
    • 订单编号
    • 产品名称
    • 数量
    • 价格

    请求

    SELECT Orders.OrderID, Orders.CustomerName
      FROM Orders 
     INNER JOIN OrderDetails
        ON Orders.OrderID = OrderDetails.OrderID
    

    将只返回在orderdetails表中也有内容的订单。

    如果您将其更改为左外联接

    SELECT Orders.OrderID, Orders.CustomerName
      FROM Orders 
      LEFT JOIN OrderDetails
        ON Orders.OrderID = OrderDetails.OrderID
    

    然后它将从orders表返回记录,即使它们没有orderdetails记录。

    您可以使用它来查找没有任何orderdetails指示可能孤立订单的订单,方法是添加一个类似于WHERE的子句 WHERE OrderDetails.OrderID IS NULL .

        10
  •  60
  •   Pratik Joshi    10 年前

    简单来说:

    内连接 ->仅从父表和子表中获取公用记录,其中父表的主键与子表中的外键匹配。

    左连接 -gt;

    伪码

    1.Take All records from left Table
    2.for(each record in right table,) {
        if(Records from left & right table matching on primary & foreign key){
           use their values as it is as result of join at the right side for 2nd table.
        } else {
           put value NULL values in that particular record as result of join at the right side for 2nd table.
        }
      }
    

    右连接 :与左连接完全相反。在右联接中,将左联接中的表名放在右联接中的右侧,得到与左联接相同的输出。

    外部连接 :显示两个表中的所有记录 No matter what . 如果左表中的记录与基于主键的右表不匹配,请使用空值作为联接的结果。

    例子:

    Example

    现在假设两张桌子

    1.employees , 2.phone_numbers_employees

    employees : id , name 
    
    phone_numbers_employees : id , phone_num , emp_id   
    

    这里,employees表是主表,phone_numbers_employees是子表(它包含 emp_id 作为连接的外键 employee.id 所以它的子表。)

    内连接

    记下两张桌子的记录 仅当Employees表的主键(其ID)与子表的外键Phone_Numbers_Employees(Emp_ID)匹配时 .

    所以查询应该是:

    SELECT e.id , e.name , p.phone_num FROM employees AS e INNER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
    

    这里只取主键=外键上的匹配行,如上所述。这里,主键=外键上的不匹配行由于联接而被跳过。

    左连接 :

    左联接保留左表的所有行,而不管右表上是否有匹配的行。

    SELECT e.id , e.name , p.phone_num FROM employees AS e LEFT JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
    

    外接 :

    SELECT e.id , e.name , p.phone_num FROM employees AS e OUTER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
    

    从图中可以看出:

    Diagram

        11
  •  54
  •   shA.t Rami Jamleh    10 年前

    你用 INNER JOIN 返回两个表中匹配的所有行。即,在结果表中,所有行和列都将具有值。

    OUTER JOIN 结果表可能有空列。外部连接可以是 LEFT RIGHT .

    LEFT OUTER JOIN 返回第一个表中的所有行,即使第二个表中没有匹配项。

    RIGHT OUTER JOIN 返回第二个表中的所有行,即使第一个表中没有匹配项。

        12
  •  52
  •   Raghu K Nair    8 年前

    This is a good explanation for joins

    对于所有类型的连接,这是一个很好的图表解释。

    来源: http://ssiddique.info/understanding-sql-joins-in-easy-way.html

        13
  •  50
  •   A_Pointar    11 年前

    INNER JOIN 要求在比较两个表时至少有一个匹配项。例如,表A和表B表示A–B(交叉点B)。

    LEFT OUTER JOIN LEFT JOIN 都一样。它给出了两个表中匹配的所有记录以及左表的所有可能性。

    同样地, RIGHT OUTER JOIN RIGHT JOIN 都一样。它给出了两个表中匹配的所有记录以及正确表的所有可能情况。

    FULL JOIN 左外连接 右外部联接 没有重复。

        14
  •  38
  •   shA.t Rami Jamleh    7 年前

    答案是每一个的意义,所以在结果中。

    注:
    SQLite 没有 RIGHT OUTER JOIN FULL OUTER JOIN .
    而且在 MySQL 没有 全外部连接 .

    我的回答基于上面 注释 .

    如果有两张这样的桌子:

    --[table1]               --[table2]
    id | name                id | name
    ---+-------              ---+-------
    1  | a1                  1  | a2
    2  | b1                  3  | b2
    

    交叉连接/外部连接:
    您可以使用 CROSS JOIN 或者只是 , 这样地:

    SELECT * FROM table1, table2
    --[OR]
    SELECT * FROM table1 CROSS JOIN table2
    
    --[Results:]
    id | name | id | name 
    ---+------+----+------
    1  | a1   | 1  | a2
    1  | a1   | 3  | b2
    2  | b1   | 1  | a2
    2  | b1   | 3  | b2
    

    内部连接:
    当您希望根据类似的关系向以上结果添加筛选器时 table1.id = table2.id 你可以使用 INNER JOIN :

    SELECT * FROM table1, table2 WHERE table1.id = table2.id
    --[OR]
    SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id
    
    --[Results:]
    id | name | id | name 
    ---+------+----+------
    1  | a1   | 1  | a2
    

    左[外部]连接:
    如果希望在上面的结果中有一个表的所有行(具有相同的关系),则可以使用 LEFT JOIN :
    (用于 右连接 换个位子就行了)

    SELECT * FROM table1, table2 WHERE table1.id = table2.id 
    UNION ALL
    SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
    --[OR]
    SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
    
    --[Results:]
    id | name | id   | name 
    ---+------+------+------
    1  | a1   | 1    | a2
    2  | b1   | Null | Null
    

    完全外部联接:
    当您还希望在结果中包含其他表的所有行时,可以使用 全外部连接 :

    SELECT * FROM table1, table2 WHERE table1.id = table2.id
    UNION ALL
    SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
    UNION ALL
    SELECT Null, Null, * FROM table2 WHERE Not table2.id In (SELECT id FROM table1)
    --[OR] (recommended for SQLite)
    SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
    UNION ALL
    SELECT * FROM table2 LEFT JOIN table1 ON table2.id = table1.id
    WHERE table1.id IS NULL
    --[OR]
    SELECT * FROM table1 FULL OUTER JOIN table2 On table1.id = table2.id
    
    --[Results:]
    id   | name | id   | name 
    -----+------+------+------
    1    | a1   | 1    | a2
    2    | b1   | Null | Null
    Null | Null | 3    | b2
    

    嗯,根据您的需要,您可以选择满足您需要的每一个;)。

        15
  •  30
  •   Sandesh    9 年前

    内部连接。

    联接正在合并两个表中的行。安 内连接 尝试根据您在查询中指定的条件来匹配这两个表,并且只返回匹配的行。如果联接中第一个表中的一行与第二个表中的两行匹配,则结果中将返回两行。如果第一个表中有一行与第二个表中的一行不匹配,则不会返回该行;同样,如果第二个表中有一行与第一个表中的一行不匹配,则不会返回该行。

    外部连接。

    左连接 尝试查找第一个表中的行与第二个表中的行匹配。如果找不到匹配项,它将返回第一个表中的列,并将第二个表中的列留空(空)。

        16
  •  24
  •   Community CDub    8 年前

    在其他答案中,我看不到关于性能和优化器的详细信息。

    有时只知道这一点是好事 INNER JOIN 是关联的,这意味着优化器有最多的选择来处理它。它可以对连接顺序进行重新排序,以便更快地保持相同的结果。优化器可以使用大多数连接模式。

    一般来说,尝试使用 内连接 而不是不同类型的连接。(当然,如果可以考虑预期结果集的话。)

    关于这种奇怪的联想行为,这里有几个很好的例子和解释:

        17
  •  19
  •   onedaywhen    9 年前

    在批评了广受欢迎的红色阴影维恩图之后,我认为发表我自己的尝试是公平的。

    虽然@martin smith的答案在很长一段时间内是最好的,但他只显示每个表中的键列,而我认为理想情况下也应该显示非键列。

    在允许的半小时内我能做的最好的,我仍然认为它不能充分地显示空值,因为在 TableB 或者那个 OUTER JOIN 实际上是一个联合而不是一个联合:

    enter image description here

        18
  •  19
  •   S.Serpooshan    6 年前

    精确的算法 INNER JOIN , LEFT/RIGHT OUTER JOIN 如下:

    1. 从第一个表中取出每一行: a
    2. 考虑它旁边第二个表中的所有行: (a, b[i])
    3. 评价 ON ... 每对条款: ON( a, b[i] ) = true/false?
      • 当条件的计算结果为 true ,返回组合行 (a,b[i]) .
      • 当到达第二张桌子的末端没有任何匹配时,这是一个 Outer Join 然后返回 (虚拟) 配对使用 Null 对于其他表的所有列: (a, Null) 对于左外部连接或 (Null, b) 用于右外部连接。这是为了确保第一个表的所有行都存在于最终结果中。

    注: 中指定的条件 ON 子句可以是任何内容,不需要使用 主键 (您不必总是引用两个表中的列)!例如:

    Inner Join vs. Left Outer Join


    enter image description here

    注: 左连接=左外部连接,右连接=右外部连接。

        19
  •  16
  •   Akshay Khale    9 年前

    最简单的定义

    内部联接:返回 匹配记录 从两张桌子。

    完全外部联接:返回匹配的和 不匹配的记录 对于来自的不匹配记录,两个表都为空 两表 .

    左外部联接:仅从上的表返回匹配和不匹配的记录 左侧 .

    右外部联接:仅从上的表返回匹配和不匹配的记录 右侧 .

    简而言之

    匹配+左不匹配+右不匹配= 全外部连接

    匹配+左不匹配= 左外连接

    匹配+右不匹配= 右外部联接

    匹配= 内连接

        20
  •  13
  •   Premraj    7 年前

    enter image description here

    • INNER JOIN 两个或多个表的最典型联接。 它返回primarykey和forignkey关系表上的数据匹配。
    • OUTER JOIN 一样 内连接 ,但也包括 NULL 结果集的数据。
      • LEFT JOIN = 内连接 +左表的数据不匹配,右表为空匹配。
      • RIGHT JOIN = 内连接 +右表的数据不匹配,左表为空匹配。
      • FULL JOIN = 内连接 +右表和左表上的数据不匹配,匹配项为空。
    • 在SQL中,当表引用自身的数据时,self-join不是关键字。使用 内连接 外部连接 我们可以编写自连接查询。

    例如:

    SELECT * 
    FROM   tablea a 
           INNER JOIN tableb b 
                   ON a.primary_key = b.foreign_key 
           INNER JOIN tablec c 
                   ON b.primary_key = c.foreign_key 
    
        21
  •  10
  •   onedaywhen    7 年前

    内部联接和外部联接有什么区别?

    它们是SQL中最常用的存在主义运算符,其中 INNER JOIN 用于“exists”和 LEFT OUTER JOIN 用于“不存在”。

    考虑这些查询:

    users who have posted and have votes
    users who have posted but have no badges
    

    寻找基于集合的解决方案(行业术语)的人会将各自的查询识别为:

    users who have posted INTERSECT users who have votes
    users who have posted MINUS users who have badges
    

    将这些转换为标准SQL:

    SELECT UserId FROM Posts
    INTERSECT 
    SELECT UserId FROM Votes;
    
    SELECT UserId FROM Posts
    EXCEPT 
    SELECT UserId FROM Badges;
    

    其他人则会按照类似的集合包含方式思考:

    users who have posted and IN the set of users who have votes
    users who have posted and NOT IN the set of users who have badges
    

    将这些转换为标准SQL:

    SELECT UserId 
      FROM Posts
     WHERE UserId IN ( SELECT UserId FROM Votes );
    
    SELECT UserId 
      FROM Posts
     WHERE UserId NOT IN ( SELECT UserId FROM Badges );
    

    有些人会考虑在集合内的“存在”,例如

    users who have posted and EXIST in the set of users who have votes
    users who have posted and do NOT EXIST in the set of users who have badges
    

    将这些转换成标准的SQL(注意,我们现在需要使用范围变量,即 p , v , b ):

    SELECT p.UserId 
      FROM Posts p
     WHERE EXISTS ( SELECT *
                      FROM Votes v
                     WHERE v.UserId = p.UserId );
    
    SELECT p.UserId 
      FROM Posts p
     WHERE NOT EXISTS ( SELECT *
                          FROM Badges b
                         WHERE b.UserId = p.UserId );
    

    但是,我发现“行业标准”方法是专门使用连接。我不知道这里的想法是什么( Law of the Instrument ? Premature optimization ?),所以我将直接转到语法:

    SELECT p.UserId 
      FROM Posts p
           INNER JOIN Votes v ON v.UserId = p.UserId;
    
    SELECT p.UserId 
      FROM Posts p
           LEFT JOIN Badges b ON b.UserId = p.UserId
     WHERE b.UserId IS NULL;
    

    需要注意的事项:

    • 唯一的投影来自 Users 但是我们仍然需要所有的范围变量( , V , )搜索条件。
    • 这个 UserId IS NULL 搜索条件“属于” OUTER JOIN 但在查询中已断开连接。
    • LEFT 行业标准:专业人员将重写查询以避免使用 RIGHT !
    • 这个 OUTER 关键字从 左外连接 被省略。

    闭幕词:

    有时连接仅用于查询,以确定值是否存在于另一个集合中。学习仔细查看正在投影的属性(中的列 SELECT 子句):如果联接表中没有,则它们只是用作存在运算符。另外,对于外部联接,请查找 <key_column> IS NULL WHERE 条款。

        22
  •  5
  •   Anands23    8 年前

    简单来说,

    1。 内部连接或同等连接: 返回仅与两个表中的条件匹配的结果集。

    2。 外部连接: 返回两个表中所有值的结果集,即使条件是否匹配。

    三。 左连接: 返回左表中所有值的结果集,仅返回与右表中条件匹配的行。

    4。 右连接: 返回右表中所有值的结果集,仅返回与左表中条件匹配的行。

    5。 完全连接: 完全联接和完全外部联接相同。

        23
  •  4
  •   Laxmi    7 年前

    1。 内部连接: 也称为连接。它返回左表和右表中的行 如果有匹配的 . 否则,它返回零个记录。

    例子:

    SELECT
      e1.emp_name,
      e2.emp_salary    
    FROM emp1 e1
    INNER JOIN emp2 e2
      ON e1.emp_id = e2.emp_id
    

    output1

    2。 完全外部联接: 也称为完全联接。它返回 所有的行 出现在左表和右表中。

    例子:

    SELECT
      e1.emp_name,
      e2.emp_salary    
    FROM emp1 e1
    FULL OUTER JOIN emp2 e2
      ON e1.emp_id = e2.emp_id
    

    output2

    三。 左外部联接: 或者简单地称为左连接。它返回左表中的所有行以及右表中的匹配行(如果有)。

    4。 右外部联接: 也称为右连接。它返回左表中的匹配行(如果有),以及右表中的所有行。

    joins

    连接的优点

    1. 执行速度更快。
        24
  •  3
  •   Sandesh    9 年前
    • 内连接 -安 内连接 使用两个等价查询中的任何一个都可以得到这两个查询的交集 桌子 也就是说,它们有共同的两行。

    • 左外连接 -A 左外连接 将给出A中的所有行,以及B中的任何公共行。

    • 全外部连接 -A 全外部连接 将给你A和B的并集,即A中的所有行和B中的所有行。如果A中的某个东西在B中没有对应的数据,那么B部分为空,副versay

        25
  •  1
  •   rashedcs    7 年前

    内部连接和外部连接的区别如下:

    1. 内部联接是基于匹配元组组合表的联接,而外部联接是基于匹配和不匹配元组组合表的联接。
    2. 内部联接合并两个表中的匹配行,其中省略了不匹配的行,而外部联接合并两个表中的行,不匹配的行用空值填充。
    3. 内部联接类似于交叉操作,而外部联接类似于联合操作。
    4. 内部联接是两种类型,而外部联接是三种类型。
    5. 内部连接较慢,而外部连接比内部连接更快。
        26
  •  1
  •   philipxy    6 年前

    left join on (阿卡 left outer join on 返回 inner join on union all 由空值扩展的不匹配的左表行。

    right join (on 阿卡 right outer join on 返回 内部连接 联合所有 由nulls扩展的不匹配的右表行。

    full join on (阿卡 full outer join on 返回 内部连接 联合所有 由空值扩展的不匹配的左表行 联合所有 由nulls扩展的不匹配的右表行。

    (SQL标准2006 SQL/FAST 7.7语法规则1,一般规则1 B,3 C和D,5 B)

    所以不要 outer join 直到你知道什么是潜在的 inner join 涉及。


    找出 what rows inner join returns .

    阅读我的评论有许多困惑和糟糕的答案。

    然后阅读我的评论这里有许多困惑和糟糕的答案。

        27
  •  1
  •   Mayank Porwal    6 年前

    考虑以下两个表:

    电磁脉冲

    empid   name    dept_id salary
    1       Rob     1       100
    2       Mark    1       300
    3       John    2       100
    4       Mary    2       300
    5       Bill    3       700
    6       Jose    6       400
    

    deptid  name
    1       IT
    2       Accounts
    3       Security
    4       HR
    5       R&D
    

    内部连接:

    大多写得像是 加入 在SQL查询中。它只返回表之间匹配的记录。

    找出所有员工及其部门名称:

    Select a.empid, a.name, b.name as dept_name
    FROM emp a
    JOIN department b
    ON a.dept_id = b.deptid
    ;
    
    empid   name    dept_name
    1       Rob     IT
    2       Mark    IT
    3       John    Accounts
    4       Mary    Accounts
    5       Bill    Security
    

    如你所见, Jose 不是打印自 电磁脉冲 在输出中作为部门ID 6 在部门表中找不到匹配项。同样地, HR R&D 行不打印自 表,因为他们在EMP表中找不到匹配项。

    所以,内部联接或只是联接,只返回匹配的行。

    左连接:

    这将返回左表中的所有记录,并且仅匹配右表中的记录。

    Select a.empid, a.name, b.name as dept_name
    FROM emp a
    LEFT JOIN department b
    ON a.dept_id = b.deptid
    ;
    
    empid   name    dept_name
    1       Rob     IT
    2       Mark    IT
    3       John    Accounts
    4       Mary    Accounts
    5       Bill    Security
    6       Jose    
    

    因此,如果您观察上面的输出,那么左表(EMP)中的所有记录都将打印为右表中的匹配记录。

    人力资源 研发 行不打印自 表,因为他们在dept_id的EMP表中找不到匹配项。

    所以,左联接返回左表中的所有行,并且只匹配右表中的行。

    也可以检查演示 here .