关于SQL: “INNER JOIN” 和 “OUTER JOIN”?有什么区别?

What is the difference between “INNER JOIN” and “OUTER JOIN”?

又是怎样做的呢?


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

  • A和B的内部连接给出了相交B的结果,即维恩图相交的内部部分。

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

实例

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

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

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

内连接

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

1
2
3
4
5
6
7
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中的任何公共行。

1
2
3
4
5
6
7
8
9
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中的任何公共行。

1
2
3
4
5
6
7
8
9
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部分为空,反之亦然。

1
2
3
4
5
6
7
8
9
10
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


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

visual explanation of joins

来源:C.L.Moffatt详细解释的SQL连接的可视化表示


我推荐杰夫的博客文章。我所见过的最好的描述,加上有一个可视化,例如:

内部连接:

enter image description here

完全外部联接:

enter image description here


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

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

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

  • 想象一个交叉连接。
  • 对步骤1中的所有行评估on子句,保留谓词评估为true的行。
  • (仅用于外部联接)在步骤2中丢失的任何外部行中重新添加。
  • (注意:在实践中,查询优化程序可能会找到比上述纯逻辑描述更有效的执行查询的方法,但最终结果必须相同)好的。

    我将从一个完整的外部连接的动画版本开始。下面是进一步的解释。好的。

    enter image description here好的。解释

    源表好的。

    enter link description here好的。

    首先从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测试选择一个不可为空或联接条件确保排除任何NULL值的列是很重要的,以便此模式正确工作,并且避免只返回恰好具有该列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'的计算结果不是真的,因此外部联接保留的行最终会被丢弃(与蓝色联接一起),从而有效地将联接转换回内部联接。好的。

    LOJtoInner好的。

    如果只包含b中颜色为绿色的行和a中的所有行,不管正确的语法是什么好的。在A.colour=B.colour和B.colour='green'上从左侧外部连接B中选择A.colour、B.colour

    enter image description here好的。SQL小提琴

    请参阅sqlfiddle.com上运行的这些示例。好的。好啊。


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

    enter image description here

    内部连接:内部联接通过基于联接谓词组合两个表(雇员和位置)的列值来创建新的结果表。查询将雇员的每一行与位置的每一行进行比较,以查找满足联接谓词的所有行对。当通过匹配非空值来满足联接谓词时,Employee和Location的每对匹配行的列值都被合并到结果行中。内部联接的SQL如下所示:

    1
    2
    3
    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 hereenter image description here

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

    左外部连接:表employee和location的左外部联接(或简单的左联接)的结果始终包含"左"表(employee)的所有记录,即使联接条件在"右"表(location)中找不到任何匹配的记录。下面是左外部联接的SQL,使用上面的表:

    1
    2
    SELECT  * FROM employee LEFT OUTER JOIN location ON employee.empID = location.empID;
    //USE OF OUTER keyword IS optional

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

    右外部连接:右外部联接(或右联接)与左外部联接非常相似,除非对表进行相反的处理。"右"表(位置)中的每一行将至少出现在联接表中一次。如果"左"表(Employee)中不存在匹配行,则对于位置不匹配的记录,Employee中的列将显示空值。这就是SQL的样子:

    1
    2
    SELECT * FROM employee RIGHT OUTER JOIN location  ON employee.empID = location.empID;
    //USE OF OUTER keyword IS optional

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

    enter image description hereenter image description here

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

    图像源

    mysql 8.0参考手册-连接语法

    Oracle加入操作


    内连接

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

    Enter image description here

    1
    2
    3
    4
    SELECT *
    FROM dbo.Students S
    INNER JOIN dbo.Advisors A
        ON S.Advisor_ID = A.Advisor_ID

    左外连接

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

    Enter image description here

    1
    2
    3
    4
    SELECT *
    FROM dbo.Students S
    LEFT JOIN dbo.Advisors A
        ON S.Advisor_ID = A.Advisor_ID

    全外部连接

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

    Enter image description here

    1
    2
    3
    4
    SELECT *
    FROM dbo.Students S
    FULL JOIN dbo.Advisors A
        ON S.Advisor_ID = A.Advisor_ID

    工具书类

    • 内部和外部联接SQL示例和联接块

    • SQL:连接


    简单来说:

    内部联接只检索匹配的行。

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

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

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

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


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

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


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

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

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

    命令

    • 订单编号
    • 客户名称

    订单详情

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

    请求

    1
    2
    3
    4
    SELECT Orders.OrderID, Orders.CustomerName
      FROM Orders
     INNER JOIN OrderDetails
        ON Orders.OrderID = OrderDetails.OrderID

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

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

    1
    2
    3
    4
    SELECT Orders.OrderID, Orders.CustomerName
      FROM Orders
      LEFT JOIN OrderDetails
        ON Orders.OrderID = OrderDetails.OrderID

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

    通过添加一个像WHERE OrderDetails.OrderID IS NULL这样的where子句,您可以使用它来查找没有任何orderdetails指示可能的孤立订单的订单。


    简单来说:

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

    左连接>

    伪码

    1
    2
    3
    4
    5
    6
    7
    8
    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

    1
    2
    3
    employees : id , name

    phone_numbers_employees : id , phone_num , emp_id

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

    内连接

    只有当Employees表的主键(其ID)与子表Phone_Numbers_Employees(EMP_ID)的外键匹配时,才取2个表的记录。

    所以查询应该是:

    1
    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;

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

    左连接:

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

    1
    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;

    外部连接:

    1
    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


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

    OUTER JOIN中,生成的表可能有空列。外部连接可以是LEFTRIGHT

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

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


    This is a good explanation for joins

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

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


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

    LEFT OUTER JOINLEFT JOIN是相同的。它给出了两个表中匹配的所有记录以及左表的所有可能性。

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

    FULL JOINLEFT OUTER JOINRIGHT OUTER JOIN的组合,没有重复。


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

    Note :
    In SQLite there is no RIGHT OUTER JOIN or FULL OUTER JOIN.
    And also in MySQL there is no FULL OUTER JOIN.

    我的答案是基于上面的笔记。

    如果有两张这样的桌子:

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

    交叉连接/外部连接:您可以使用CROSS JOIN或仅使用,这样拥有所有这些表数据:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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

    1
    2
    3
    4
    5
    6
    7
    8
    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:(对于右连接,只需更改表的位置)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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

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


    内部连接。

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

    外部连接。

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


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

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

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

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

    • 左外部联接是否关联?
    • SQL中的联接顺序有关系吗?


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

  • 从第一张表中每行取一行:a
  • 考虑它旁边第二个表中的所有行:(a, b[i])
  • 对每一对评估ON ...条款:ON( a, b[i] ) = true/false?
    • 当条件评估为true时,返回合并行(a, b[i])
    • 当到达第二个表的末尾而没有任何匹配时,这是一个OUTER JOIN,然后使用Null为其他表的所有列返回一个(虚拟)对:(a, Null)表示左外部联接,(Null, b)表示右外部联接。这是为了确保第一个表的所有行都存在于最终结果中。
  • 注意:ON子句中指定的条件可以是任何东西,不需要使用主键(也不需要总是引用两个表中的列)!例如:

    • ... ON T1.title = T2.title AND T1.version < T2.version(=>请参阅本文作为示例用法:仅选择列上最大值的行)
    • ... ON T1.y IS NULL
    • ... ON 1 = 0(同样品)

    Inner Join vs. Left Outer Join

    enter image description here

    注:左联接=左外联接,右联接=右外联接。


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

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

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

    enter image description here


    最简单的定义

    内部联接:返回两个表中匹配的记录。

    完全外部联接:返回两个表中匹配的和不匹配的记录,对于两个表中不匹配的记录,返回空值。

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

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

    简而言之

    匹配+左不匹配+右不匹配=完全外部联接

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

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

    匹配=内部联接


    enter image description here

    • inner join两个或多个表的最典型联接。它返回primarykey和forignkey关系表上的数据匹配。
    • outer joininner join相同,但也包括NULL结果集的数据。
      • LEFT JOIN=inner join+左表数据不匹配,右表NULL匹配。
      • RIGHT JOIN=inner join+左表NULL匹配右表不匹配数据。
      • FULL JOIN=inner join+与NULL匹配的左、右表数据不匹配。
    • 在SQL中,当表引用自身的数据时,self-join不是关键字。使用inner joinouter join我们可以编写自连接查询。

    例如:

    1
    2
    3
    4
    5
    6
    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


    What is the difference between"INNER JOIN" and"OUTER JOIN"?

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

    考虑这些查询:

    1
    2
    users who have posted AND have votes
    users who have posted but have no badges

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

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

    将这些转换为标准SQL:

    1
    2
    3
    4
    5
    6
    7
    SELECT UserId FROM Posts
    INTERSECT
    SELECT UserId FROM Votes;

    SELECT UserId FROM Posts
    EXCEPT
    SELECT UserId FROM Badges;

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

    1
    2
    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:

    1
    2
    3
    4
    5
    6
    7
    SELECT UserId
      FROM Posts
     WHERE UserId IN ( SELECT UserId FROM Votes );

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

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

    1
    2
    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(注意,我们现在需要使用范围变量,即pvb

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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 );

    但是,我发现"行业标准"方法是专门使用连接。我不知道这里的想法是什么(仪器定律?过早优化?),所以我将直接转到语法:

    1
    2
    3
    4
    5
    6
    7
    8
    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,但是我们仍然需要所有这些范围变量(pvb来搜索条件。
    • UserId IS NULL搜索条件"属于"OUTER JOIN但在查询中断开连接。
    • LEFT是行业标准:专业人员会重写查询,避免使用RIGHT
    • 省略LEFT OUTER JOIN中的OUTER关键字。

    闭幕词:

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


    简单来说,

    1.inner join或equi join:返回仅与两个表中的条件匹配的结果集。

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

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

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

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


    1.内部联接:也称为联接。它返回左表和右表中的行,只有在匹配时才返回。否则,它返回零个记录。

    例子:

    1
    2
    3
    4
    5
    6
    SELECT
      e1.emp_name,
      e2.emp_salary    
    FROM emp1 e1
    INNER JOIN emp2 e2
      ON e1.emp_id = e2.emp_id

    output1

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

    例子:

    1
    2
    3
    4
    5
    6
    SELECT
      e1.emp_name,
      e2.emp_salary    
    FROM emp1 e1
    FULL OUTER JOIN emp2 e2
      ON e1.emp_id = e2.emp_id

    output2

    3.左外联接:或简称左联接。它返回左表中的所有行以及右表中的匹配行(如果有)。

    4.右外接:又称右接。它返回左表中的匹配行(如果有),以及右表中的所有行。

    joins

    连接的优点

  • 执行速度更快。

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

    • 左外部联接-左外部联接将提供A中的所有行,以及B中的所有公共行。

    • 完全外部联接-完全外部联接将为您提供A和B的联接,即A中的所有行和B中的所有行。如果A中的某个内容在B中没有相应的数据,则B部分为空,副versay


    left join on(aka left outer join on返回inner join onunion all行不匹配的左表行,扩展为空。

    right join (onaka right outer join on返回inner join onunion all行不匹配的右表行,扩展为空。

    full join on(aka full outer join on返回inner join onunion all不匹配的左表行,由nulls扩展;union all不匹配的右表行,由nulls扩展。

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

    所以在你知道inner join的基础内容之前,不要使用outer join

    找出inner join返回的行。

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

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


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

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

  • 考虑以下两个表:

    电磁脉冲

    1
    2
    3
    4
    5
    6
    7
    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

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

    内部连接:

    主要是作为SQL查询中的join编写的。它只返回表之间匹配的记录。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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

    如上所述,输出中没有从EMP打印Jose,因为其部门ID 6在部门表中找不到匹配项。同样,由于在EMP表中找不到匹配项,因此不会从Department表中打印HRR&D行。

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

    左连接:

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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)中的所有记录都将打印为右表中的匹配记录。

    HRR&D行不从部门表中打印,因为它们在部门ID的EMP表中找不到匹配项。

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

    也可以在这里查看演示。