“INNER JOIN”和“OUTER JOIN”有什么区别?
问题描述:
另外,LEFT JOIN、RIGHT JOIN 和 FULL JOIN 如何适应?
保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com
解决方案1:
一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会
假设您要加入没有重复的列,这是一种非常常见的情况:
A 和 B 的内连接给出了 A 相交 B 的结果,即维恩图相交的内部部分。
A 和 B 的外连接给出了 A 联合 B 的结果,即维恩图联合的外部部分。
例子
假设您有两个表,每个表都有一个列,数据如下:
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
huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。
最好通过在表 B 中添加值 4 的另一行来扩充示例。这将表明内部连接不需要在相等的行数上。
一个很好的解释,但是这个陈述:A 和 B 的外部连接给出了 A 联合 B 的结果,即维恩图联合的外部部分。措辞不准确。除了以下之一之外,外连接将给出 A 与 B 相交的结果:所有 A(左连接)、所有 B(右连接)或所有 A 和所有 B(完全连接)。只有最后一个场景才是真正的联合 B。不过,这是一个写得很好的解释。
@Ameer,谢谢。加入不保证顺序,您需要添加 ORDER BY 子句。
@Damian 是的,OUTER JOIN 和 FULL OUTER JOIN 是等价的,LEFT/RIGHT JOIN 等价于 LEFT/RIGHT OUTER JOIN,同样的 INNER JOIN 等价于一个简单的 JOIN
我对此表示反对,因为它是错误的。请考虑删除答案,因为它会误导几代计算机科学专业的学生,他们被大量的 upcote 数量所愚弄。维恩图不解释连接。连接的内部不是交集。
解决方案2:
保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com
维恩图并没有真正为我做这件事。
例如,它们没有显示交叉连接和内部连接之间的任何区别,或者更一般地显示不同类型的连接谓词之间的任何区别,或者提供了推理它们将如何操作的框架。
理解逻辑处理是无可替代的,而且无论如何都比较容易掌握。
想象一下交叉连接。针对步骤 1 中的所有行评估 on 子句,保持谓词评估为 true 的那些行(仅适用于外部连接)添加回在步骤 2 中丢失的任何外部行。
(注意:在实践中,查询优化器可能会找到比上述纯逻辑描述更有效的查询执行方式,但最终结果必须相同)
我将从完整外部联接的动画版本开始。进一步的解释如下。
https://i.stack.imgur.com/VUkfU.gif
解释
源表
https://i.stack.imgur.com/LVYKx.png
首先从 CROSS JOIN(又名笛卡尔积)开始。这没有 ON 子句,只是返回两个表中的每个行组合。
从交叉连接 B 中选择 A.Colour、B.Colour
https://i.stack.imgur.com/cv3t6.png
内连接和外连接有一个“ON”子句谓词。
内部联接。评估交叉连接结果中所有行的“ON”子句中的条件。如果为 true,则返回连接的行。否则丢弃它。
左外连接。与内连接相同,然后对于左表中与任何不匹配的任何行输出这些与右表列的 NULL 值。
右外连接。与内连接相同,然后对于右表中与任何不匹配的任何行输出这些与左表列的 NULL 值。
全外连接。与内连接相同,然后保留左外连接中的左不匹配行和右外连接中的右非匹配行。
一些例子
从 A.Colour 上的 A INNER JOIN B 中选择 A.Colour、B.Colour = B.Colour
以上是经典的 equi join。
https://i.stack.imgur.com/a8IHd.png
动画版
https://i.stack.imgur.com/kZcvR.gif
SELECT A.Colour, B.Colour 从 A.Colour NOT IN (‘Green’,‘Blue’) 上的 A INNER JOIN B
内连接条件不一定是相等条件,也不需要引用两个(甚至任何一个)表中的列。对交叉连接的每一行计算 A.Colour NOT IN (‘Green’,‘Blue’) 会返回。
https://i.stack.imgur.com/ZwoCi.png
SELECT A.Colour, B.Colour 从 A INNER JOIN B ON 1 =1
对于交叉连接结果中的所有行,连接条件的计算结果为真,因此这与交叉连接相同。 16行的图我就不再赘述了。
从 A.Colour 的左外连接 B 中选择 A.Colour、B.Colour = B.Colour
外部联接的逻辑评估方式与内部联接相同,只是如果左表中的一行(对于左联接)根本不与右侧表中的任何行联接,则它会保留在 NULL 的结果中右侧列的值。
https://i.stack.imgur.com/4bzv2.png
从 A.Colour = B.Colour 的左外连接 B 中选择 A.Colour,B.Colour,其中 B.Colour 为 NULL
这只是将先前的结果限制为仅返回 B.Colour IS NULL 所在的行。在这种特殊情况下,这些将是保留的行,因为它们在右侧表中不匹配,并且查询返回表 B 中不匹配的单个红色行。这称为反半连接。
为 IS NULL 测试选择一个不可为空或连接条件可确保排除任何 NULL 值的列非常重要,以便此模式正常工作并避免只带回发生的行除了不匹配的行之外,该列还有一个 NULL 值。
https://i.stack.imgur.com/d6CVF.png
从 A.Colour = B.Colour 的右外连接 B 中选择 A.Colour、B.Colour
右外连接的作用类似于左外连接,除了它们保留右表中不匹配的行并且空扩展左列。
https://i.stack.imgur.com/LIOW4.png
从 A.Colour = B.Colour 的完整外部连接 B 中选择 A.Colour、B.Colour
全外连接结合了左连接和右连接的行为,并保留左右表中不匹配的行。
https://i.stack.imgur.com/iVoqu.png
从 1 = 0 的完整外部连接 B 中选择 A.Colour、B.Colour
交叉连接中没有与 1=0 谓词匹配的行。两侧的所有行都使用正常的外部连接规则保留,另一侧表的列中为 NULL。
https://i.stack.imgur.com/gtIhf.png
选择 COALESCE(A.Colour, B.Colour) 作为颜色从 FULL OUTER JOIN B ON 1 = 0
对前面的查询稍作修改,就可以模拟两个表中的 UNION ALL。
https://i.stack.imgur.com/WPu9W.png
从 A.Colour = B.Colour 的左外连接 B 中选择 A.Colour、B.Colour 其中 B.Colour = ‘Green’
请注意,WHERE 子句(如果存在)逻辑上在连接之后运行。一个常见的错误是执行左外连接,然后在右表上包含一个 WHERE 子句,该条件最终排除了不匹配的行。以上最终执行了外部连接…
https://i.stack.imgur.com/4bzv2.png
…然后“Where”子句运行。 NULL= ‘Green’ 不评估为 true,因此外部连接保留的行最终被丢弃(连同蓝色的行),有效地将连接转换回内部连接。
https://i.stack.imgur.com/tRHdf.png
如果打算只包括 B 中颜色为绿色的行以及 A 中的所有行,无论正确的语法是
从 A.Colour = B.Colour 和 B.Colour = ‘Green’ 的左外连接 B 中选择 A.Colour、B.Colour
https://i.stack.imgur.com/cvJ1s.png
SQL小提琴
请参阅这些示例 run live at SQLFiddle.com。
我会说,虽然这对我来说几乎没有维恩图那么有效,但我很欣赏人们的不同和学习方式不同,这是一个很好的解释,与我以前见过的任何不同,所以我支持@ypercube奖励积分。也很好地解释了在 JOIN 子句与 WHERE 子句中添加附加条件的区别。向你致敬,马丁·史密斯。
@OldPro 我想维恩图还可以,但它们对如何表示交叉连接或区分一种连接谓词(例如等连接)保持沉默。在交叉连接结果的每一行上评估连接谓词的心理模型,然后在外部连接中添加不匹配的行,最后评估 where 对我来说效果更好。
维恩图适用于表示联合、交叉点和差异,但不适用于连接。它们对于非常简单的连接有一些小的教育价值,即连接条件在唯一列上的连接。
@Arth - 不,你错了。 SQL Fiddle sqlfiddle.com/#!3/9eecb7db59d16c80417c72d1/5155 这是维恩图无法说明的。
你是怎么做这些动画的?很好的答案,我唯一不喜欢的是你谦虚地说维恩图不适合你。现实情况是,它们不足以模拟正在发生的事情,这很重要,以免人们产生错误的想法。
解决方案3:
huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。
连接用于组合来自两个表的数据,结果是一个新的临时表。连接是基于称为谓词的东西执行的,谓词指定了用于执行连接的条件。内连接和外连接之间的区别在于,内连接将仅返回基于连接谓词实际匹配的行。例如,让我们考虑 Employee 和 Location 表:
员工
EmpID EmpName 13 杰森 8 亚历克斯 3 拉姆 17 巴布 25 约翰逊
地点
EmpID EmpLoc 13 San Jose 8 Los Angeles 3 Pune, India 17 Chennai, India 39 Bangalore, India
内连接:- 内连接通过基于连接谓词组合两个表(员工和位置)的列值来创建一个新的结果表。该查询将 Employee 的每一行与 Location 的每一行进行比较,以找到满足连接谓词的所有行对。当通过匹配非 NULL 值满足连接谓词时,Employee 和 Location 的每对匹配行的列值将组合成一个结果行。下面是内部连接的 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
外连接:外连接不需要两个连接表中的每条记录都有匹配的记录。即使不存在其他匹配记录,连接表也会保留每条记录。外连接进一步细分为左外连接和右外连接,具体取决于保留哪个表的行(左或右)。
左外连接:- 员工和位置表的左外连接(或简称为左连接)的结果始终包含“左”表(员工)的所有记录,即使连接条件在“右”表(位置)。下面是左外连接的 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 在员工位置表中没有条目,但他仍然包含在结果中,但位置字段为空。
右外连接:- 右外连接(或右连接)与左外连接非常相似,但表的处理方式相反。 “右”表(位置)中的每一行将至少出现在连接表中一次。如果“左”表 (Employee) 中不存在匹配的行,则 NULL 将出现在 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 印度班加罗尔
请注意,虽然没有列出在班加罗尔工作的员工,但它仍然包含在结果中,员工字段为空。
完全外连接:- 完全外连接或完全连接是通过在连接结果中包含不匹配的行来保留不匹配的信息,使用完全外连接。它包括两个表中的所有行,无论另一个表是否具有匹配值。
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 印度班加罗尔
MySQL 8.0 Reference Manual - Join Syntax
Oracle Join operations
迄今为止最好的答案,替代语法 - 这就是我一直在寻找的,谢谢!
维恩图被贴错标签。请参阅我对问题和其他答案的评论。而且大多数这种语言都很差。例如:“当通过匹配非 NULL 值满足连接谓词时,每对匹配的 Employee 和 Location 行的列值将组合成一个结果行。”不,不是“当通过匹配非 NULL 值满足连接谓词时”。除了条件作为一个整体是真还是假之外,行中的值并不重要。对于真实条件,某些值很可能为 NULL。
@Persistence 表格需要的是文本,它是表格初始化代码,格式化为适合复制、粘贴和运行的列。
解决方案4:
huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。
内部联接
仅检索匹配的行,即 A intersect B。
https://i.stack.imgur.com/Zkk3I.jpg
SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
左外连接
选择第一个表中的所有记录,以及第二个表中与连接键匹配的任何记录。
https://i.stack.imgur.com/Z584b.jpg
SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
全外连接
选择第二个表中的所有记录,以及第一个表中与连接键匹配的任何记录。
https://i.stack.imgur.com/c1QF3.jpg
SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
参考
内连接和外连接 SQL 示例和 Join 块
SQL:连接
工具的名称是什么?我觉得这很有趣,因为它显示了行数和维恩图
@GrijeshChauhan 是的,但是您可以尝试使用 wine 运行它。
哦!是的,我..我用葡萄酒使用 SQLyog .. 还有 PlayOnLinux
您的文字不清楚且错误。 “仅匹配的行”是来自 A 和 B 的交叉连接的行,并且检索到的(A 内部连接 B)不是 A 相交 B,而是(A 左连接 B)相交(A 右连接 B)。 “选定”行不是来自 A 和 B,它们来自 A 交叉连接 B 和来自 A 和 B 的行的空扩展值。
@TusharGupta-curioustushar 您应该包括“用于 SQL 示例的表”
解决方案5:
huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。
简单来说:
内连接只检索匹配的行。
而外连接从一个表中检索匹配的行以及其他表中的所有行…结果取决于您使用的是哪一个:
左:右表中的匹配行和左表中的所有行
右:左表中的匹配行和右表中的所有行或
完整:所有表中的所有行。有没有匹配都没关系
@nomen 不是这个答案解决了它,但是如果左右集/圆包含(分别)左和右连接的行,则 INNER JOIN 是一个交集,而 FULL OUTER JOIN 是相应的 UNION。 PS这个答案不清楚输入与输出中的行。它将“在左/右表中”与“在左/右中具有左/右部分”混淆了,它使用“匹配行”与“全部”来表示从其他表中按行扩展的行与按空值扩展的行。
解决方案6:
huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。
内连接仅在连接的另一(右侧)存在匹配记录时才显示行。
(左)外部联接在左侧显示每条记录的行,即使在联接的另一(右侧)侧没有匹配的行。如果没有匹配的行,另一侧(右侧)的列将显示 NULL。
解决方案7:
huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。
内部联接要求联接表中存在具有相关 ID 的记录。
即使右侧不存在任何内容,外部联接也会返回左侧的记录。
例如,您有一个 Orders 和一个 OrderDetails 表。它们通过“OrderID”相关联。
订单
订单编号
顾客姓名
订单详细信息
订单详情 ID
订单编号
产品名称
数量
价格
请求
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)。我不确定附加条件,它们混合得很好......
解决方案8:
huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。
简单来说:
内连接 -> 仅从父表和子表中获取公共记录,其中父表的主键与子表中的外键匹配。
左连接->
伪代码
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 中的所有记录。如果左表中的记录根据Primary,Forieign key与右表不匹配,则使用NULL值作为连接结果。
例子 :
https://i.stack.imgur.com/pCErn.png
现在让我们假设 2 个表
1.employees , 2.phone_numbers_employees
employees : id , name
phone_numbers_employees : id , phone_num , emp_id
这里,employees 表是 Master 表,phone_numbers_employees 是子表(它包含 emp_id 作为外键连接 employee.id 所以它的子表。)
内连接
仅当员工表的主键(其 id)与子表 phone_numbers_employees(emp_id)的外键匹配时,才获取 2 个表的记录。
所以查询将是:
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;
从图形上看,它看起来像:
https://i.stack.imgur.com/hMKKt.jpg
结果与主/唯一/候选键和外键无关(本身)。 baviour 可以而且应该在不参考它们的情况下进行描述。计算一个交叉连接,然后过滤掉不符合 ON 条件的行;此外,对于外连接行,过滤/不匹配的行由 NULL 扩展(每个 LEFT/RIGHT/FULL 并包括在内。
SQL 连接始终是主键/外键匹配的假设导致了对维恩图的这种滥用。请相应地修改您的答案。
解决方案9:
HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com
您使用 INNER JOIN 从两个表中返回所有匹配的行。即在结果表中,所有行和列都有值。
在 OUTER JOIN 中,结果表可能有空列。外部联接可以是 LEFT 或 RIGHT。
LEFT OUTER JOIN 返回第一个表中的所有行,即使第二个表中没有匹配项。
RIGHT OUTER JOIN 返回第二个表中的所有行,即使第一个表中没有匹配项。
解决方案10:
huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。
INNER JOIN 要求在比较两个表时至少有一个匹配项。例如,表 A 和表 B 表示 A ٨ B(A 交集 B)。
LEFT OUTER JOIN 和 LEFT JOIN 相同。它给出了两个表中匹配的所有记录以及左表的所有可能性。
同样,RIGHT OUTER JOIN 和 RIGHT JOIN 是相同的。它给出了两个表中匹配的所有记录以及正确表的所有可能性。
FULL JOIN 是 LEFT OUTER JOIN 和 RIGHT OUTER JOIN 的组合,没有重复。
解决方案11:
打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!
答案在于每一个的含义,所以在结果中。
注意:在 SQLite 中没有 RIGHT OUTER JOIN 或 FULL OUTER JOIN。而且在 MySQL 中也没有 FULL OUTER JOIN。
我的回答是基于上面的注释。
当您有两个这样的表时:
--[table1] --[table2]
id | name id | name
---+------- ---+-------
1 | a1 1 | a2
2 | b1 3 | b2
CROSS JOIN / OUTER JOIN :您可以使用 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
INNER JOIN :当您想根据 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 [OUTER] JOIN :当您希望上述结果中的一个表的所有行具有相同的关系时,您可以使用 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 :如果您还想在结果中包含另一个表的所有行,您可以使用 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。
原文链接:https://www.huntsbot.com/qa/QQ2v/what-is-the-difference-between-inner-join-and-outer-join?lang=zh_CN
huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求