“INNER JOIN”和“OUTER JOIN”有啥区别?

Posted

技术标签:

【中文标题】“INNER JOIN”和“OUTER JOIN”有啥区别?【英文标题】:What is the difference between "INNER JOIN" and "OUTER JOIN"?“INNER JOIN”和“OUTER JOIN”有什么区别? 【发布时间】:2010-09-07 12:03:28 【问题描述】:

还有LEFT JOINRIGHT JOINFULL JOIN如何适应?

【问题讨论】:

only one下面的答案&cmets&他们的引用实际上解释了维恩图是如何表示算子的:圆相交区域表示A JOIN B中的行集。每个圆唯一的区域表示您通过获取其表中不参与 A JOIN B 的行并将对另一个表唯一的列添加为 NULL 获得的行集。 (而且大多数人给 A 和 B 提供了一个模糊的、虚假的圈子对应关系。) @DanteTheSmith 不,这与此处的图表存在相同的问题。请参阅我在该问题上方的评论以及在该博客文章下方的评论:“杰夫在 cmets 的几页下拒绝了他的博客”。维恩图以集合的形式显示元素。只需尝试准确识别这些图表中的集合是什么以及元素是什么。集合不是表和元素不是它们的行。也可以连接任意两个表,因此 PK 和 FK 无关紧要。都是假的。你正在做成千上万其他人所做的事情——得到一个模糊的印象你(错误地)认为是有道理的。跨度> 我之前的评论是关于a confused repudiated Jeff Atwood blog post。 我的第 1 条评论的链接是外部链接,但 i.stack.imgur.com 为inner、left 提供了输出(非输入) 插图的永久副本& full 加入(绿色)。 【参考方案1】:

假设您要加入没有重复的列,这是一种非常常见的情况:

A 和 B 的内连接给出 A 与 B 相交的结果,即 Venn diagram 交集的内部。

A 和 B 的外连接给出 A 联合 B 的结果,即 Venn diagram 联合的外部部分。

示例

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

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

请注意,(1,2) 是 A 独有的,(3,4) 是常见的,(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

【讨论】:

最好通过在表 B 中添加另一行值为 4 的行来扩充示例。这将表明内部连接不需要在相等的行数上。 一个很好的解释,但是这个陈述:A 和 B 的外部连接给出了 A 联合 B 的结果,即维恩图联合的外部部分。 t 措辞准确。除了以下之一之外,外连接将给出 A 与 B 相交的结果:所有 A(左连接)、所有 B(右连接)或所有 A 和所有 B(完全连接)。只有最后一种情况才是真正的联合 B。不过,解释得很好。 @Ameer,谢谢。 Join 不保证有顺序,需要添加 ORDER BY 子句。 @Damian 是的,OUTER JOIN 和 FULL OUTER JOIN 是等价的,还有 LEFT/RIGHT JOIN 等价于 LEFT/RIGHT OUTER JOIN,同样的 INNER JOIN 等价于一个简单的 JOIN跨度> 我对此投了反对票,因为它是错误的。请考虑删除答案,因为它会误导几代计算机科学专业的学生,​​他们被大量的 upcote 数量所愚弄。维恩图不解释连接。连接的内部不是交集。【参考方案2】:

联接用于合并来自两个表的数据,结果是一个新的临时表。连接是基于称为谓词的东西执行的,谓词指定了用于执行连接的条件。内连接和外连接之间的区别在于,内连接将仅返回基于连接谓词实际匹配的行。 例如,让我们考虑 Employee 和 Location 表:

员工

EmpID EmpName
13 Jason
8 Alex
3 Ram
17 Babu
25 Johnson

位置

EmpID EmpLoc
13 San Jose
8 Los Angeles
3 Pune, India
17 Chennai, India
39 Bangalore, India

内连接:- 内连接通过基于连接谓词组合两个表(EmployeeLocation)的列值来创建一个新的结果表。该查询将 Employee 的每一行与 Location 的每一行进行比较,以找到满足连接谓词的所有行对。当通过匹配非 NULL 值满足连接谓词时,EmployeeLocation 的每对匹配行的列值组合成一个结果行。 下面是内部连接的 SQL 的样子:

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

现在,运行该 SQL 的结果如下所示:

Employee.EmpId Employee.EmpName Location.EmpId Location.EmpLoc
13 Jason 13 San Jose
8 Alex 8 Los Angeles
3 Ram 3 Pune, India
17 Babu 17 Chennai, India

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

左外连接:- EmployeeLocation 表的左外连接(或简称为左连接)的结果总是包含“左”表(Employee)的所有记录>),即使连接条件在“正确”表 (Location) 中没有找到任何匹配记录。 使用上面的表格,左外连接的 SQL 如下所示:

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

现在,运行此 SQL 的结果如下所示:

Employee.EmpId Employee.EmpName Location.EmpId Location.EmpLoc
13 Jason 13 San Jose
8 Alex 8 Los Angeles
3 Ram 3 Pune, India
17 Babu 17 Chennai, India
25 Johnson NULL NULL

请注意,虽然 Johnson 在员工位置表中没有条目,但他仍包含在结果中,但位置字段为空。

右外连接:- 右外连接(或右连接)与左外连接非常相似,除了表的处理方式相反。 “右”表 (Location) 中的每一行将至少出现在连接表中一次。如果“左”表 (Employee) 中不存在匹配的行,则 Employee 的列中将出现在 Location 中没有匹配的记录时间>。 这就是 SQL 的样子:

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

使用上面的表格,我们可以展示右外连接的结果集是什么样的:

Employee.EmpId Employee.EmpName Location.EmpId Location.EmpLoc
13 Jason 13 San Jose
8 Alex 8 Los Angeles
3 Ram 3 Pune, India
17 Babu 17 Chennai, India
NULL NULL 39 Bangalore, India

请注意,虽然没有列出在班加罗尔工作的员工,但它仍然包含在结果中,员工字段为空。

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

Employee.EmpId Employee.EmpName Location.EmpId Location.EmpLoc
13 Jason 13 San Jose
8 Alex 8 Los Angeles
3 Ram 3 Pune, India
17 Babu 17 Chennai, India
25 Johnson NULL NULL
NULL NULL 39 Bangalore, India

mysql 8.0 Reference Manual - Join Syntax

Oracle Join operations

【讨论】:

迄今为止最好的答案,替代语法 - 这就是我一直在寻找的,谢谢! 维恩图被贴错标签。有关问题和其他答案,请参阅我的 cmets。而且大多数这种语言都很差。例如:“当通过匹配非 NULL 值满足连接谓词时,每对匹配的 Employee 和 Location 行的列值将组合成一个结果行。”不,不是“当通过匹配非 NULL 值满足连接谓词时”。除了条件作为一个整体是真还是假之外,行中的值并不重要。对于真实条件,某些值很可能为 NULL。 @Persistence 表格需要的文本是表格初始化代码,格式化为适合复制、粘贴和运行的列。【参考方案3】:

演示

设置

进入psql 并创建一个包含猫和人类的小型数据库。 您可以复制粘贴整个部分。

CREATE DATABASE catdb;
\c catdb;
\pset null '[NULL]' -- how to display null values

CREATE TABLE humans (
  name text primary key
);
CREATE TABLE cats (
  human_name text references humans(name),
  name text
);

INSERT INTO humans (name)
VALUES ('Abe'), ('Ann'), ('Ben'), ('Jen');

INSERT INTO cats (human_name, name)
VALUES
('Abe', 'Axel'),
(NULL, 'Bitty'),
('Jen', 'Jellybean'),
('Jen', 'Juniper');

查询

这是我们将多次运行的查询,将[SOMETHING JOIN] 更改为各种类型以查看结果。

SELECT
humans.name AS human_name,
cats.name AS cat_name
FROM humans
[SOMETHING JOIN] cats ON humans.name = cats.human_name
ORDER BY humans.name;

INNER JOIN 返回所有人猫对。 任何没有猫的人或没有人的猫都被排除在外。

 human_name | cat_name
------------+-----------
 Abe        | Axel
 Jen        | Jellybean
 Jen        | Juniper

FULL OUTER JOIN 返回所有人类和所有猫,如果两边都不匹配,则返回 NULL

 human_name | cat_name
------------+-----------
 Abe        | Axel
 Ann        | [NULL]
 Ben        | [NULL]
 Jen        | Jellybean
 Jen        | Juniper
 [NULL]     | Bitty

LEFT OUTER JOIN 返回所有人类(左表)。 任何没有猫的人都会在cat_name 列中获得NULL。 任何没有人类的猫都被排除在外。

 human_name | cat_name
------------+-----------
 Abe        | Axel
 Ann        | [NULL]
 Ben        | [NULL]
 Jen        | Jellybean
 Jen        | Juniper

A RIGHT OUTER JOIN 返回所有猫(右表)。 任何没有人类的猫都会在human_name 列中获得NULL。 任何没有猫的人都被排除在外。

 human_name | cat_name
------------+-----------
 Abe        | Axel
 Jen        | Jellybean
 Jen        | Juniper
 [NULL]     | Bitty

内部与外部

您可以看到,虽然 INNER JOIN 只获得匹配的对,但每种 OUTER 连接都包含一些没有匹配的项目。

但是,实际的单词INNEROUTER 不需要出现在查询中:

JOIN 本身暗示 INNER LEFT JOINRIGHT JOINOUTER JOIN 都暗示 OUTER

【讨论】:

【参考方案4】:

关于这个主题有很多错误信息,包括 Stack Overflow 上的这里。

left join on(又名left outer join on)返回inner join onunion allnulls扩展的不匹配的左表行。

right join (on aka right outer join on) 返回 inner join onunion allnulls 扩展的不匹配的右表行。

full join on(又名full outer join on)返回inner join onrowsunion allnulls扩展的不匹配的左表行union allnulls扩展的不匹配的右表行。

(SQL Standard 2006 SQL/Foundation 7.7 语法规则 1,一般规则 1 b、3 c & d、5 b。)

因此,在您知道inner join 涉及到什么基础之前,请​​不要outer join


找出 inner join on 返回的行:CROSS JOIN vs INNER JOIN in SQL

这也解释了为什么维恩图对内连接和外连接没有帮助。 有关为什么维恩(-like)图对连接没有帮助的更多信息:Venn Diagram for Natural Join

【讨论】:

我确实读过你的很多cmets。当您说“正确解释的维恩图可以表示内部连接与外部连接”时,您的意思是当观察者正确解释时还是维恩图本身?如果是后者,请画出来:) 我不确定你想说什么。我说的是维恩图作为元素集的标准解释。 (因为图表的某些用途甚至无法做到这一点。)应用程序的“正确”包括说明集合和/或元素是什么。请参阅本页顶部的评论,其中有 50 人对内连接和外连接的维恩图表示赞同。我会将我的一些 cmets 编辑到这个问题中。我不想在这篇文章中出现维恩图。 我也不想要维恩图! 我必须承认,尽管我在 cmets 中的措辞很快,但由于 SQL 涉及包和空值,并且 SQL 文化没有通用术语来命名和区分相关概念,因此即使是清楚地解释维恩图的元素如何以 1:1 的比例输出“行”,更不用说输入“行”了。或者内部或外部联接做什么,更不用说它们的区别了。 “value”可能包含也可能不包含 NULL,“row”可能是值列表 vs 表值或变量中的插槽 & “=”可能是 SQL “=” vs 相等性。 类似于我们的笛卡尔积与关系积讨论,我怀疑维恩图对于已经了解连接类型之间差异的人们来说很有意义! 【参考方案5】:

这里有很多很好的答案以及非常准确的relational algebra 示例。这是一个非常简化的答案,可能对遇到 SQL 编码难题的业余或新手编码员有所帮助。

基本上,JOIN 查询通常归结为两种情况:

对于A 数据子集的SELECT

当您要查找的相关 B 数据必须根据数据库设计存在时,请使用 INNER JOIN; 当您要查找的相关B 数据可能可能不存在每个数据库设计时,请使用LEFT JOIN

【讨论】:

【参考方案6】:

通过示例更容易解释联接:

模拟存储在不同表中的人员和电子邮件,

表 A 和表 B 由 Table_A 连接。id = Table_B.name_id

内连接

仅显示匹配的 id 行。

外部联接

显示表 A 的匹配 ID 和不匹配行。

显示表 B 的匹配 ID 和不匹配行。

显示两个表中匹配的 id 和不匹配的行。

注意:完全外连接在 MySQL 上不可用

【讨论】:

【参考方案7】:

总体思路

请参阅Martin Smith 的answer 以获得对不同连接的更好说明和解释,尤其是FULL OUTER JOINRIGHT OUTER JOINLEFT OUTER JOIN 之间的区别。

这两个表构成了下面JOINs 表示的基础:

交叉连接

SELECT *
  FROM citizen
 CROSS JOIN postalcode

结果将是所有组合的笛卡尔积。不需要JOIN 条件:

内连接

INNER JOIN 等同于:JOIN

SELECT *
  FROM citizen    c
  JOIN postalcode p ON c.postal = p.postal

结果将是满足所需JOIN 条件的组合:

左外连接

LEFT OUTER JOINLEFT JOIN 相同

SELECT *
  FROM citizen         c
  LEFT JOIN postalcode p ON c.postal = p.postal

结果将是来自citizen 的所有内容,即使postalcode 中没有匹配项。再次需要JOIN 条件:

播放数据

所有示例均在 Oracle 18c 上运行。它们可以在dbfiddle.uk 获得,这也是表格截图的来源。

CREATE TABLE citizen (id      NUMBER,
                      name    VARCHAR2(20),
                      postal  NUMBER,  -- <-- could do with a redesign to postalcode.id instead.
                      leader  NUMBER);

CREATE TABLE postalcode (id      NUMBER,
                         postal  NUMBER,
                         city    VARCHAR2(20),
                         area    VARCHAR2(20));

INSERT INTO citizen (id, name, postal, leader)
              SELECT 1, 'Smith', 2200,  null FROM DUAL
        UNION SELECT 2, 'Green', 31006, 1    FROM DUAL
        UNION SELECT 3, 'Jensen', 623,  1    FROM DUAL;

INSERT INTO postalcode (id, postal, city, area)
                 SELECT 1, 2200,     'BigCity',         'Geancy'  FROM DUAL
           UNION SELECT 2, 31006,    'SmallTown',       'Snizkim' FROM DUAL
           UNION SELECT 3, 31006,    'Settlement',      'Moon'    FROM DUAL  -- <-- Uuh-uhh.
           UNION SELECT 4, 78567390, 'LookoutTowerX89', 'Space'   FROM DUAL;

使用JOINWHERE 时边界模糊

交叉连接

CROSS JOIN 导致行为 The General Idea/INNER JOIN:

SELECT *
  FROM citizen          c
  CROSS JOIN postalcode p
 WHERE c.postal = p.postal -- < -- The WHERE condition is limiting the resulting rows

使用CROSS JOIN 获得LEFT OUTER JOIN 的结果需要一些技巧,例如添加NULL 行。省略了。

内连接

INNER JOIN 成为笛卡尔积。和The General Idea一样/CROSS JOIN:

SELECT *
  FROM citizen    c
  JOIN postalcode p ON 1 = 1  -- < -- The ON condition makes it a CROSS JOIN

这是内部连接真正可以看作是交叉连接的地方,结果与条件不匹配。这里没有任何结果行被删除。

使用INNER JOIN 得到LEFT OUTER JOIN 的结果也需要技巧。省略了。

左外连接

LEFT JOIN 的结果为 The General Idea/CROSS JOIN:

SELECT *
  FROM citizen         c
  LEFT JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN

LEFT JOIN 的结果为 The General Idea/INNER JOIN:

SELECT *
  FROM citizen         c
  LEFT JOIN postalcode p ON c.postal = p.postal
 WHERE p.postal IS NOT NULL -- < -- removed the row where there's no mathcing result from postalcode

维恩图的问题

在“sql join cross inner external”上的图像互联网搜索将显示大量维恩图。我曾经在我的桌子上放了一份印刷版。但表示存在问题。

维恩图非常适合集合论,其中一个元素可以在一个或两个集合中。但是对于数据库,在我看来,一个“集合”中的元素似乎是表中的一行,因此也不存在于任何其他表中。多个表中不存在一行。一行对表来说是唯一的。

自连接是一种极端情况,其中每个元素实际上在两个集合中都是相同的。但它仍然存在以下任何问题。

集合A 代表左边的集合(citizen 表),集合B 是右边的集合(postalcode 表)在下面的讨论中。

交叉连接

两个集合中的每个元素都与另一个集合中的每个元素匹配,这意味着我们需要每个B 元素的A 数量和每个A 元素的B 数量才能正确表示这个笛卡尔积。集合论不适用于集合中的多个相同元素,因此我发现维恩图正确表示它是不切实际/不可能的。 UNION 似乎根本不适合。

行是不同的。 UNION 总共有 7 行。但它们与常见的SQL 结果集不兼容。这根本不是CROSS JOIN 的工作方式:

试着像这样表示它:

..但现在它看起来就像一个INTERSECTION,它肯定不是。此外,INTERSECTION 中没有任何元素实际上位于两个不同集合中的任何一个中。但是,它看起来很像类似这样的可搜索结果:

作为参考,CROSS JOINs 的一个可搜索结果可以在Tutorialgateway 上看到。 INTERSECTION,就像这个一样,是空的。

内连接

元素的值取决于JOIN 条件。在每一行都对该条件唯一的条件下表示这一点是可能的。含义 id=x 仅适用于 one 行。一旦Acitizen)表中的一行在JOIN条件下匹配Bpostalcode)表中的多行,结果与CROSS JOIN有同样的问题:多次表示,而集合论并不是为此而生的。在唯一性条件下,图表可以工作,但请记住,JOIN 条件决定了元素在图表中的位置。仅查看 JOIN 条件的值以及该行的其余部分以进行乘车:

当使用带有ON 1 = 1 条件的INNER JOIN 使其变成CROSS JOIN 时,这种表示完全崩溃了。

使用 self-JOIN,行实际上是两个表中的相同元素,但将表同时表示为 AB 不是很合适。例如,一个常见的 self-JOIN 条件使 A 中的元素匹配 B 中的 不同 元素是 ON A.parent = B.child,使得匹配从 AB单独的元素。从像这样的SQL 示例中:

SELECT *
  FROM citizen c1
  JOIN citizen c2 ON c1.id = c2.leader

意思是史密斯是格林和詹森的领袖。

外连接

当一行与另一表中的行有多个匹配时,麻烦又开始了。这更加复杂,因为OUTER JOIN 可以被认为与空集匹配。但是在集合论中,任何集合C 和一个空集的并集总是只是C。空集什么也没增加。这个LEFT OUTER JOIN 的表示通常只显示所有A,以说明A 中的行被选中,而不管B 是否匹配。然而,“匹配元素”具有与上图相同的问题。它们取决于条件。而空集似乎已经飘到A

WHERE 子句 - 有意义

CROSS JOIN 中查找所有行,其中包含 Smith 和月球上的邮政编码:

SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE c.name = 'Smith'
   AND p.area = 'Moon';

现在维恩图不用于反映JOIN。它用于WHERE 子句:

..这是有道理的。

当 INTERSECT 和 UNION 有意义时

相交

正如所解释的,INNER JOIN 并不是真正的INTERSECT。但是INTERSECTs 可以用于单独查询的结果。这里的维恩图很有意义,因为来自单独查询的元素实际上是属于一个结果或两者的行。相交显然只会返回两个查询中都存在该行的结果。这个SQL会和上面WHERE产生同一行,维恩图也一样:

SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE c.name = 'Smith'
INTERSECT
SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE p.area = 'Moon';

联合

OUTER JOIN 不是UNION。但是UNION 在与INTERSECT 相同的条件下工作,导致返回结合SELECTs 的所有结果:

SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE c.name = 'Smith'
UNION
SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE p.area = 'Moon';

相当于:

SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE c.name = 'Smith'
   OR p.area = 'Moon';

..并给出结果:

这里的维恩图也很有意义:

当它不适用时

重要说明是,这些仅在两个 SELECT 的结果结构相同时才有效,从而可以进行比较或联合。这两个的结果将无法实现:

SELECT *
  FROM citizen
 WHERE name = 'Smith'
SELECT *
  FROM postalcode
 WHERE area = 'Moon';

..尝试将结果与UNION 结合起来会得到一个

ORA-01790: expression must have same datatype as corresponding expression

更多兴趣请阅读Say NO to Venn Diagrams When Explaining JOINs 和sql joins as venn diagram。两者都涵盖EXCEPT

【讨论】:

【参考方案8】:

inner joinouter join的区别如下:

    Inner join 是基于匹配元组组合表的连接,而outer join 是基于匹配和不匹配元组组合表的连接。 Inner join 合并两个表中的匹配行,其中不匹配的行被省略,而outer join 合并两个表中的行,不匹配的行填充空值。 Inner join 类似于交集运算,而outer join 类似于联合运算。 Inner join 是两种类型,而outer join 是三种类型。 outer joininner join 快。

【讨论】:

外连接结果与内连接相同,但加上了一些额外的行,所以我不知道你为什么认为外连接会更快。还有这些“两种类型”的内连接是什么?我想您是指外部的完整,左侧和右侧? 外连接不比内连接快。【参考方案9】:

INNER JOIN 两个或多个表的最典型连接。 它返回表 ON primarykey 和 forignkey 关系上的数据匹配。 OUTER JOININNER JOIN 相同,但它还包括 ResultSet 上的 NULL 数据。 LEFT JOIN = INNER JOIN + 表的数据不匹配,Null 在右表匹配。 RIGHT JOIN = INNER JOIN + 表数据不匹配,Null左表匹配。 FULL JOIN = INNER JOIN + 左右两表上的数据不匹配,Null 匹配。 自联接不是 SQL 中的关键字,当表引用数据时,它本身就称为自联接。使用INNER JOINOUTER 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 

【讨论】:

【参考方案10】:

考虑以下 2 个表格:

EMP

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 查询中大多写成 JOIN。它只返回表之间匹配的记录。

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

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 不是从输出中的 EMP 打印的,因为它的 dept_id 6 在 Department 表中找不到匹配项。同样,HRR&amp;D 行不会从 Department 表中打印出来,因为它们在 Emp 表中没有找到匹配项。

因此,INNER JOIN 或只是 JOIN,只返回匹配的行。

左连接:

这将返回 LEFT 表中的所有记录,并仅返回 RIGHT 表中的匹配记录。

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    

因此,如果您观察上述输出,则 LEFT 表 (Emp) 中的所有记录都将与 RIGHT 表中的匹配记录一起打印。

HRR&amp;D 行未从 Department 表中打印,因为它们未在 dept_id 的 Emp 表中找到匹配项。

因此,LEFT JOIN 返回左表中的所有行,并且只返回右表中的匹配行。

也可以查看DEMOhere。

【讨论】:

【参考方案11】:

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) 用于 LEFT外连接或(Null, b) 用于右外连接。这是为了确保第一个表的所有行都存在于最终结果中。

注意:ON 子句中指定的条件可以是任何东西,不需要使用主键(你不需要总是参考两个表中的列)!例如:

... ON T1.title = T2.title AND T1.version &lt; T2.version ( => 看这篇文章作为示例用法:Select only rows with max value on a column) ... ON T1.y IS NULL ... ON 1 = 0(仅作为示例)


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

【讨论】:

【参考方案12】:

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

即使右侧不存在任何内容,外连接也会返回左侧的记录。

例如,您有一个 Orders 和一个 OrderDetails 表。它们通过“OrderID”相关联。

订单

订单编号 客户名称

订单详情

OrderDetailID 订单编号 产品名称 数量 价格

请求

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

只会返回在 OrderDetails 表中也有内容的订单。

如果你把它改成 OUTER LEFT JOIN

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

然后它会从 Orders 表中返回记录,即使它们没有 OrderDetails 记录。

您可以通过添加诸如WHERE OrderDetails.OrderID IS NULL 之类的 where 子句来使用它来查找没有任何 OrderDetails 指示可能孤立订单的订单。

【讨论】:

我很欣赏这个简单而现实的例子。我成功地将SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c, categories_description cd WHERE c.id = cd.categories_id AND c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASC 之类的请求更改为SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c INNER JOIN categories_description cd ON c.id = cd.categories_id WHERE c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASC (MySQL)。我不确定附加条件,它们混合得很好......【参考方案13】:

维恩图并不适合我。

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

理解逻辑处理是无可替代的,反正掌握起来也相对简单。

    想象一下交叉连接。 针对步骤 1 中的所有行评估 on 子句,保持谓词评估为 true 的行 (仅适用于外部连接)在步骤 2 中丢失的任何外部行中重新添加。

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

我将从完全外部联接的动画版本开始。进一步的解释如下。


说明

源表

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

从交叉连接 B 中选择 A.Colour、B.Colour

内连接和外连接有一个“ON”子句谓词。

Inner Join。评估交叉连接结果中所有行的“ON”子句中的条件。如果为 true,则返回连接的行。否则丢弃。 左外连接。与内连接相同,然后对于左表中与任何不匹配的任何行输出右表列的 NULL 值。 右外连接。 与内连接相同,然后对于右表中与任何不匹配的任何行输出这些与左表列的 NULL 值。 完全外连接。与内连接相同,然后保留左外连接中的左不匹配行和右外连接中的右不匹配行。

一些例子

从 A.Colour = B.Colour 的内部连接 ​​B 中选择 A.Colour、B.Colour

以上是经典的 equi join。

动画版

SELECT A.Colour, B.Colour FROM A INNER JOIN B ON A.Colour NOT IN ('Green','Blue')

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

SELECT A.Colour, B.Colour FROM A INNER JOIN B ON 1 =1

对于交叉连接结果中的所有行,连接条件的计算结果为真,因此这与交叉连接相同。 16行的图我就不重复了。

从 A.Colour = B.Colour 的左外连接 B 中选择 A.Colour、B.Colour

外部联接的逻辑评估方式与内部联接相同,除了如果左表中的一行(用于左联接)根本不与右侧表中的任何行联接,则它会保留在结果中NULL 右侧列的值。

SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour IS NULL

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

IS NULL 测试选择一个不可为空或连接条件确保排除任何NULL 值的列非常重要,这样该模式才能正常工作并避免只返回除了不匹配的行之外,该列恰好具有NULL 值的行。

从 A.Colour = B.Colour 的右外连接 B 中选择 A.Colour、B.Colour

右外连接的作用类似于左外连接,除了它们保留右表中不匹配的行并且空扩展左列。

从 A.Colour = B.Colour 的完整外部连接 B 中选择 A.Colour、B.Colour

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

SELECT A.Colour, B.Colour FROM A FULL OUTER JOIN B ON 1 = 0

交叉连接中没有与1=0 谓词匹配的行。两边的所有行都使用正常的外连接规则保留,另一边表的列中为 NULL。

SELECT COALESCE(A.Colour, B.Colour) AS Color FROM A FULL OUTER JOIN B ON 1 = 0

对前面的查询稍作修改,可以模拟两个表的UNION ALL

在 A.Colour = B.Colour WHERE B.Colour = 'Green' 的左外连接 B 中选择 A.Colour、B.Colour

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

... 然后“Where”子句运行。 NULL= 'Green' 不会评估为 true,因此外部连接保留的行最终会被丢弃(连同蓝色的行),有效地将连接转换回内部连接。

如果打算只包含 B 中颜色为绿色的行,以及 A 中的所有行,无论语法是否正确

从 A.Colour = B.Colour AND B.Colour = 'Green' 的左外连接 B 中选择 A.Colour、B.Colour

SQL 小提琴

查看这些示例run live at SQLFiddle.com。

【讨论】:

我会说,虽然这对我来说几乎不像维恩图那样适用,但我很欣赏人们会因人而异,学习方式也不同,这是一个很好的解释,与我所见过的任何不同之前,所以我支持@ypercube 奖励积分。也很好地解释了在 JOIN 子句与 WHERE 子句中添加附加条件的区别。向你致敬,马丁·史密斯。 @OldPro 我想维恩图还可以,但它们没有说明如何表示交叉连接,或者区分一种连接谓词,例如 equi join。在交叉连接结果的每一行上评估连接谓词然后在不匹配的行中添加回外部连接并最终评估 where 对我来说效果更好的心理模型。 维恩图适用于表示联合、交叉和差异,但不适用于连接。它们对于非常简单的连接有一些小的教育价值,即连接条件在唯一列上的连接。 @Arth - 不,你错了。 SQL Fiddle sqlfiddle.com/#!3/9eecb7db59d16c80417c72d1/5155 这是维恩图无法说明的。 你是怎么做这些动画的?很好的答案,我唯一不喜欢的是你谦虚地说维恩图不适合你。现实情况是,它们不足以模拟正在发生的事情,这很重要,以免人们产生错误的想法。【参考方案14】:

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

注意:SQLite 中没有RIGHT OUTER JOINFULL OUTER JOIN。 在MySQL 中也没有FULL OUTER JOIN

我的回答是基于以上注意

当你有两个这样的表时:

--[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

左 [OUTER] 加入: 如果您想在上述结果中包含一个表的所有行 - 具有相同的关系 - 您可以使用 LEFT JOIN: (对于 RIGHT 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

完全外连接: 当您还想在结果中包含其他表的所有行时,您可以使用FULL OUTER 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)
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

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

【讨论】:

您可以在注释中添加,MySQL 中也没有 full outer join【参考方案15】:

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

例子:

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

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

例子:

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

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

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

连接的优点

    执行速度更快。

【讨论】:

这仅在表具有相同的列集时才正确。 (它将内连接与交集和完全连接与联合混淆。)“匹配”也是未定义的。阅读我的其他 cmets。【参考方案16】:

简单来说,

1.INNER JOIN OR EQUI JOIN:返回只匹配两个表中的条件的结果集。

2.OUTER JOIN :返回两个表中所有值的结果集,即使条件匹配与否。

3.LEFT JOIN :返回左表所有值的结果集,只返回与右表条件匹配的行。

4.RIGHT JOIN :返回右表中所有值的结果集,并且只返回与左表中条件匹配的行。

5.FULL JOIN : Full Join 和 Full outer Join 是一样的。

【讨论】:

【参考方案17】:

内连接 - 使用任一等效查询的内连接给出两个的交集,即两个它们有共同的行。

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

完全外连接 - A 完全外连接会给你 A 和 B 的并集,即 A 中的所有行和 B 中的所有行. 如果 A 中的某物在 B 中没有对应的数据,则 B 部分为空,反之亦然

【讨论】:

这既错误又不清楚。除非表具有相同的列,否则联接不是交集。外部联接没有来自 A 或 B 的行,除非它们具有相同的列,在这种情况下不会添加空值。你试图说些什么,但你没有说出来。您没有正确或清楚地解释。 @philipxy:不同意你的说法Join is not an intersection unless the tables have the same columns 不。你可以加入任何你想要的列,如果值匹配,它们会加入。 该评论与您的​​回答一样不清楚。 (我想你可能会想,结果的公共列的子行值集是每个输入的公共列的子行值集的交集;但这不是你写的。你不清楚。) 我的意思是,当它是具有相同列的输入的自然内部连接时,连接只是输入的交集。您错误地使用了“intersection”和“union”这两个词。【参考方案18】:

最简单的定义

Inner Join:从两个表中返回匹配的记录

完全外连接:从两个表中返回匹配和不匹配的记录,对于两个表中的不匹配记录返回 null。

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

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

简短

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

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

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

匹配 = 内连接

【讨论】:

这太棒了,并解释了为什么 join 不能按预期对时间序列索引起作用。相隔一秒的时间戳是无与伦比的。 @yeliabsalohcin 您没有在此处解释“按预期”或在您对问题的评论中“有效”。这只是你奇怪地期望别人有的一些无法解释的个人误解。如果您在阅读时将单词视为草率-误解清晰的写作和/或接受不清晰的写作-就像您在这里写作时一样,那么您可能会产生误解。事实上,像这里的大多数人一样,这个答案是不清楚和错误的。当输入列集不同时,“内部联接:从两个表中返回匹配的记录”是错误的。它试图说某件事,但它不是。 (见我的回答。)【参考方案19】:

内连接。

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

外连接。

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

【讨论】:

【参考方案20】:

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

虽然@Martin Smith 的回答是这群人中最好的,但他只显示每个表的关键列,而我认为理想情况下也应该显示非关键列。

在允许的半小时内我能做的最好的事情,我仍然不认为它充分表明空值是由于TableB 中缺少键值或OUTER JOIN 实际上是一个联合而不是一个联合加入:

【讨论】:

问题是询问 INNER 和 OUTER 连接之间的差异,但不一定是左外连接 lol @LearnByReading:我右边的图片是右外连接,即将TableA a LEFT OUTER JOIN TableB b替换为TableB B RIGHT OUTER JOIN TableA a【参考方案21】:

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

OUTER JOIN 中,结果表可能有空列。外连接可以是LEFTRIGHT

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

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

【讨论】:

【参考方案22】:

我在其他答案中没有看到关于性能和优化器的太多细节。

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

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

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

Are left outer joins associative? Does the join order matter in SQL?

【讨论】:

使用一种连接类型而不是另一种连接类型不可能是“好习惯”。您使用的连接决定了您想要的数据。如果你使用不同的,那你就错了。另外,在 Oracle 中,至少这个答案是完全错误的。这听起来对一切都完全错误,你没有证据。你有证据吗? 1.我的意思是 try 使用。我看到很多人在没有任何充分理由的情况下到处使用 LEFT OUTER 连接。 (连接的列不为空。)在这些情况下,使用 INNER 连接肯定会更好。 2. 我添加了一个链接,可以更好地解释非关联行为。 据我所知,INNER JOIN 在大多数情况下都比LEFT JOIN 慢,人们可以使用LEFT JOIN 而不是INNER JOIN 通过添加WHERE 来删除意外的NULL结果;)。 这些 cmets 让我有点不确定。为什么你认为INNER 比较慢? 取决于引擎。 gnu join、joinkeys、DB2、MySQL。性能陷阱比比皆是,例如松散的输入或显式转换。【参考方案23】:

简单来说:

内连接 -> 只取父表和子表中的公共记录,父表的主键匹配子表的外键。

左加入 ->

伪代码

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中的所有记录。如果 Left table 中的记录根据 Primary , Forieign key 与右表不匹配,则使用 NULL 值作为连接结果。

示例:

现在假设有 2 个表

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所以它的子表。)

内连接

获取 2 个表的记录仅当员工表的主键(其 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;

图表看起来像:

【讨论】:

结果与主/唯一/候选键和外键无关(本身)。 baviour 可以而且应该在不参考它们的情况下进行描述。计算一个交叉连接,然后过滤掉不符合 ON 条件的行;此外,对于外连接行,过滤/不匹配的行由 NULL 扩展(每个 LEFT/RIGHT/FULL 并包括在内。 SQL 连接总是匹配主键/外键的假设导致了对维恩图的这种滥用。请相应地修改您的答案。【参考方案24】:

内连接仅在连接的另一(右侧)存在匹配记录时才显示行。

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

【讨论】:

【参考方案25】:

内连接

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

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

左外连接

选择第一个表中的所有记录,以及第二个表中的所有记录 与连接键匹配的表。

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

完全外连接

选择第二个表中的所有记录,以及第一个表中的任何记录 与连接键匹配的表。

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

参考文献

Inner and outer joins SQL examples and the Join block

SQL: JOINS

【讨论】:

工具名称是什么?我觉得这很有趣,因为它显示了行数和维恩图 @GrijeshChauhan 是的,但是您可以尝试使用 wine 运行它。 哦!是的,我..我用葡萄酒使用 SQLyog.. 还有PlayOnLinux 您的文字不清楚且错误。 “仅匹配的行”是来自 A 和 B 的交叉连接的行,并且检索到的(A 内连接 B)不是 A 相交 B,而是(A 左连接 B)相交(A 右连接 B)。 “选定”行不是来自 A 和 B,它们来自 A 交叉连接 B 和来自 A 和 B 的行的空扩展值。 @TusharGupta-curioustushar 您应该包含“用于 SQL 示例的表”【参考方案26】:

简单来说:

内连接只检索匹配的行。

外连接从一个表中检索匹配的行以及其他表中的所有行......结果取决于您使用的是哪一个:

:右表匹配行和左表所有行

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

完整:所有表中的所有行。有没有匹配都无所谓

【讨论】:

@nomen 不是这个答案解决了它,但 INNER JOIN 是一个交集,而 FULL OUTER JOIN 是相应的 UNION if 左右集/圆圈包含的行(分别)LEFT & RIGHT 加入。 PS这个答案不清楚输入与输出中的行。它将“在左/右表中”与“在左/右中有左/右部分”混淆了,它使用“匹配行”与“全部”来表示从其他表中按行扩展的行与空值。跨度> 【参考方案27】:

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

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

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

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

【讨论】:

以上是关于“INNER JOIN”和“OUTER JOIN”有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

SQL中inner join,outer join和cross join的区别

SQL中inner join,outer join和cross join的区别

SQL中inner join,outer join和cross join的区别

left join ,right join ,inner join,outer join,union all,union有啥区别?怎么用?

“INNER JOIN”和“OUTER JOIN”有啥区别?

“INNER JOIN”和“OUTER JOIN”有啥区别?