MySQL - LEFT JOIN、RIGHT JOIN、INNER JOIN、CROSS JOIN、FULL JOIN

本文涉及的产品
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS Agent(兼容OpenClaw),2核4GB
简介: MySQL - LEFT JOIN、RIGHT JOIN、INNER JOIN、CROSS JOIN、FULL JOIN

一、Join语法概述

join 用于多表中字段之间的联系,语法如下:

... FROMtable1INNER|LEFT|RIGHTJOINtable2ONconditiona

able1:左表;table2:右表。

JOIN 按照功能大致分为如下三类:

INNER JOIN(内连接或等值连接:取得两个表中存在连接匹配关系的记录。


LEFT JOIN(左连接):取得左表(table1)完全记录,即是右表(table2)并无对应匹配记录。


RIGHT JOIN(右连接):与 LEFT JOIN 相反,取得右表(table2)完全记录,即是左表(table1)并无匹配对应记录。

注意:mysql不支持Full join,不过可以通过UNION 关键字来合并 LEFT JOIN 与 RIGHT JOIN来模拟FULL join.


Ps:我们了解到在 MySQL 中,INNER JOIN...ON,JOIN...ON,逗号...WHERE,CROSS JOIN...ON 是一样的含义。但是在标准 SQL 中,它们并不等价。


当然“逗号...WHERE”和上述的“JOIN”之间底层还是有区别的


JOIN 是生成一张临时表,然后 WHERE 进一步筛选,所以如果在 JOIN 的时候就能筛选掉的话(替 WHERE 分担一些性能开销)那是最好不过了。


接下来给出一个列子用于解释下面几种分类。如下两个表(A,B)

mysql>selectA.id,A.name,B.namefromA,BwhereA.id=B.id;
+----+-----------+-------------+|id|name|name|+----+-----------+-------------+|1|Pirate|Rutabaga||2|Monkey|Pirate||3|Ninja|DarthVader||4|Spaghetti|Ninja|+----+-----------+-------------+4rowsinset (0.00sec)

二、Inner join

内连接,也叫等值连接,inner join产生同时符合A和B的一组数据。

mysql>select*fromAinnerjoinBonA.name=B.name;
+----+--------+----+--------+|id|name|id|name|+----+--------+----+--------+|1|Pirate|2|Pirate||3|Ninja|4|Ninja|+----+--------+----+--------+

image.png


三、Left join

mysql>select*fromAleftjoinBonA.name=B.name;
#或者:select * from A left outer join B on A.name = B.name;+----+-----------+------+--------+|id|name|id|name|+----+-----------+------+--------+|1|Pirate|2|Pirate||2|Monkey|NULL|NULL||3|Ninja|4|Ninja||4|Spaghetti|NULL|NULL|+----+-----------+------+--------+4rowsinset (0.00sec)

left join,(或left outer join:在Mysql中两者等价,推荐使用left join.)左连接从左表(A)产生一套完整的记录,与匹配的记录(右表(B)) .如果没有匹配,右侧将包含null。

image.png

如果想只从左表(A)中产生一套记录,但不包含右表(B)的记录,可以通过设置where语句来执行,如下:

mysql>select*fromAleftjoinBonA.name=B.namewhereA.idisnullorB.idisnull;
+----+-----------+------+------+|id|name|id|name|+----+-----------+------+------+|2|Monkey|NULL|NULL||4|Spaghetti|NULL|NULL|+----+-----------+------+------+2rowsinset (0.00sec)

image.png

同理,还可以模拟inner join. 如下:

mysql>select*fromAleftjoinBonA.name=B.namewhereA.idisnotnullandB.idisnotnull;
+----+--------+------+--------+|id|name|id|name|+----+--------+------+--------+|1|Pirate|2|Pirate||3|Ninja|4|Ninja|+----+--------+------+--------+2rowsinset (0.00sec)

求差集:

根据上面的例子可以求差集,如下:

SELECT*FROMALEFTJOINBONA.name=B.nameWHEREB.idISNULLunionSELECT*FROMArightJOINBONA.name=B.nameWHEREA.idISNULL;
# 结果+------+-----------+------+-------------+|id|name|id|name|+------+-----------+------+-------------+|2|Monkey|NULL|NULL||4|Spaghetti|NULL|NULL||NULL|NULL|1|Rutabaga||NULL|NULL|3|DarthVader|+------+-----------+------+-------------+

image.png


四、Right join

mysql>select*fromArightjoinBonA.name=B.name;
+------+--------+----+-------------+|id|name|id|name|+------+--------+----+-------------+|NULL|NULL|1|Rutabaga||1|Pirate|2|Pirate||NULL|NULL|3|DarthVader||3|Ninja|4|Ninja|+------+--------+----+-------------+4rowsinset (0.00sec)

同left join。


五、Cross join

cross join:交叉连接,得到的结果是两个表的乘积,即笛卡尔积


笛卡尔(Descartes)乘积又叫直积。假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)}。可以扩展到多个集合的情况。类似的例子有,如果A表示某学校学生的集合,B表示该学校所有课程的集合,则A与B的笛卡尔积表示所有可能的选课情况。

mysql>select*fromAcrossjoinB;
+----+-----------+----+-------------+|id|name|id|name|+----+-----------+----+-------------+|1|Pirate|1|Rutabaga||2|Monkey|1|Rutabaga||3|Ninja|1|Rutabaga||4|Spaghetti|1|Rutabaga||1|Pirate|2|Pirate||2|Monkey|2|Pirate||3|Ninja|2|Pirate||4|Spaghetti|2|Pirate||1|Pirate|3|DarthVader||2|Monkey|3|DarthVader||3|Ninja|3|DarthVader||4|Spaghetti|3|DarthVader||1|Pirate|4|Ninja||2|Monkey|4|Ninja||3|Ninja|4|Ninja||4|Spaghetti|4|Ninja|+----+-----------+----+-------------+16rowsinset (0.00sec)
#再执行:mysql> select * from A inner join B; 试一试#在执行mysql> select * from A cross join B on A.name = B.name; 试一试

实际上,在 MySQL 中(仅限于 MySQL) CROSS JOIN 与 INNER JOIN 的表现是一样的,在不指定 ON 条件得到的结果都是笛卡尔积,反之取得两个表各自匹配的结果。

INNER JOIN(或者用“,”表示)与 CROSS JOIN 可以省略 INNER 或 CROSS 关键字,因此下面的 SQL 效果是一样的:

... FROMtable1INNERJOINtable2... FROMtable1CROSSJOINtable2... FROMtable1JOINtable2

六、Full join

mysql>select*fromAleftjoinBonB.name=A.name->union->select*fromArightjoinBonB.name=A.name;
+------+-----------+------+-------------+|id|name|id|name|+------+-----------+------+-------------+|1|Pirate|2|Pirate||2|Monkey|NULL|NULL||3|Ninja|4|Ninja||4|Spaghetti|NULL|NULL||NULL|NULL|1|Rutabaga||NULL|NULL|3|DarthVader|+------+-----------+------+-------------+6rowsinset (0.00sec)

全连接产生的所有记录(双方匹配记录)在表A和表B。如果没有匹配,则对面将包含null。

MySQL本身不支持full join(全连接),但可以通过union来实现。

image.png


七、性能优化

1、显示(explicit) inner join VS 隐式(implicit) inner join

如:

select*fromtableainnerjointablebona.id=b.id;

VS

selecta.*, b.*fromtablea, tablebwherea.id=b.id;

我在数据库中比较(10w数据)得之,它们用时几乎相同,第一个是显示的inner join,后一个是隐式的inner join。

2.left join/right join VS inner join

尽量用inner join.避免 LEFT JOIN 和 NULL.

在使用left join(或right join)时,应该清楚的知道以下几点:

(1) on 与 where 的执行顺序


ON 条件(“A LEFT JOIN B ON 条件表达式”中的ON)用来决定如何从 B 表中检索数据行。如果 B 表中没有任何一行数据匹配 ON 的条件,将会额外生成一行所有列为 NULL 的数据,在匹配阶段 WHERE 子句的条件都不会被使用。仅在匹配阶段完成以后,WHERE 子句条件才会被使用。它将从匹配阶段产生的数据中检索过滤。


所以我们要注意:在使用Left (right) join的时候,一定要在先给出尽可能多的匹配满足条件,减少Where的执行。如:

PS:这部分有些不妥,感谢 wxweven 指正:


这部分的内容,博主写的有些欠妥当,不知道博主有没有实际运行测试过,下面说说我的看法:


(1)首先关于on和where的用法,如果直接把where里面的条件拿到on里面去,结果是跟原来的不一致的,所以博主说的“在使用Left (right) join的时候,一定要在先给出尽可能多的匹配满足条件,减少Where的执行”是不成立的,因为筛选条件放在on或者where,产生的是不同的结果,不能说为了性能就把where中的条件放到on中。


PASS

select*fromAinnerjoinBonB.name=A.nameleftjoinConC.name=B.nameleftjoinDonD.id=C.idwhereC.status>1andD.status=1;

Great

select*fromAinnerjoinBonB.name=A.nameleftjoinConC.name=B.nameandC.status>1leftjoinDonD.id=C.idandD.status=1

从上面例子可以看出,尽可能满足ON的条件,而少用Where的条件。从执行性能来看第二个显然更加省时。

(2) 注意 ON 子句和 WHERE 子句的不同

如作者举了一个列子:

mysql>SELECT*FROMproductLEFTJOINproduct_detailsON (product.id=product_details.id)
ANDproduct_details.id=2;
+----+--------+------+--------+-------+|id|amount|id|weight|exist|+----+--------+------+--------+-------+|1|100|NULL|NULL|NULL||2|200|2|22|0||3|300|NULL|NULL|NULL||4|400|NULL|NULL|NULL|+----+--------+------+--------+-------+4rowsinset (0.00sec)
mysql>SELECT*FROMproductLEFTJOINproduct_detailsON (product.id=product_details.id)
WHEREproduct_details.id=2;
+----+--------+----+--------+-------+|id|amount|id|weight|exist|+----+--------+----+--------+-------+|2|200|2|22|0|+----+--------+----+--------+-------+1rowinset (0.01sec)

从上可知,第一条查询使用 ON 条件决定了从 LEFT JOIN的 product_details表中检索符合的所有数据行。第二条查询做了简单的LEFT JOIN,然后使用 WHERE 子句从 LEFT JOIN的数据中过滤掉不符合条件的数据行。


(3) 尽量避免子查询,而用join

往往性能这玩意儿,更多时候体现在数据量比较大的时候,此时,我们应该避免复杂的子查询。如下:

PASS

insertintot1(a1) selectb1fromt2wherenotexists(select1fromt1wheret1.id=t2.r_id); 

Great

insertintot1(a1)  
selectb1fromt2leftjoin (selectdistinctt1.idfromt1 ) t1ont1.id=t2.r_idwheret1.idisnull;  

附:

image.png

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
算法 关系型数据库 MySQL
join查询可以⽆限叠加吗?MySQL对join查询有什么限制吗?
大家好,我是 V 哥。本文详细探讨了 MySQL 中 `JOIN` 查询的限制及其优化方法。首先,`JOIN` 查询不能无限叠加,存在资源(CPU、内存、磁盘 I/O)、性能和语法等方面的限制。过多的 `JOIN` 操作会导致数据库性能急剧下降。其次,介绍了三种常见的 `JOIN` 查询算法:嵌套循环连接(NLJ)、索引嵌套连接(INL)和基于块的嵌套循环连接(BNL),并分析了它们的触发条件和性能特点。最后,分享了优化 `JOIN` 查询的方法,包括 SQL 语句优化、索引优化、数据库配置调整等。关注 V 哥,了解更多技术干货,点赞👍支持,一起进步!
391 3
|
算法 关系型数据库 MySQL
浅析MySQL Join Reorder算法
本文浅析了MySQL Join Reorder算法的流程,cost计算,剪枝算法等,希望通过本文能帮助大家了解MySQL优化器生成执行计划的具体流程。
|
SQL 关系型数据库 MySQL
Mysql中from多表跟join表的区别
Mysql中from多表跟join表的区别
1285 0
|
9月前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
570 158
|
9月前
|
关系型数据库 MySQL 数据库
自建数据库如何迁移至RDS MySQL实例
数据库迁移是一项复杂且耗时的工程,需考虑数据安全、完整性及业务中断影响。使用阿里云数据传输服务DTS,可快速、平滑完成迁移任务,将应用停机时间降至分钟级。您还可通过全量备份自建数据库并恢复至RDS MySQL实例,实现间接迁移上云。
|
9月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
1467 152
|
9月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
1068 156
|
9月前
|
缓存 监控 关系型数据库
使用MYSQL Report分析数据库性能(中)
使用MYSQL Report分析数据库性能
610 156
|
9月前
|
缓存 监控 关系型数据库
使用MYSQL Report分析数据库性能(上)
最终建议:当前系统是完美的读密集型负载模型,优化重点应放在减少行读取量和提高数据定位效率。通过索引优化、分区策略和内存缓存,预期可降低30%的CPU负载,同时保持100%的缓冲池命中率。建议每百万次查询后刷新统计信息以持续优化
717 161
|
10月前
|
存储 运维 关系型数据库
从MySQL到云数据库,数据库迁移真的有必要吗?
本文探讨了企业在业务增长背景下,是否应从 MySQL 迁移至云数据库的决策问题。分析了 MySQL 的优势与瓶颈,对比了云数据库在存储计算分离、自动化运维、多负载支持等方面的优势,并提出判断迁移必要性的五个关键问题及实施路径,帮助企业理性决策并落地迁移方案。

推荐镜像

更多