MySQL多表联查——内连、外连

前言

SQL语句以前一直没当回事,总觉得就是select + where组合,前几天面试被拷打了,生产环境下的多表联查很不熟练,现在补上。

多表联查主要借助连接join实现,将两张表的内容进行关联,具体可分为:内连inner join、外连outer join、交叉连接cross join、全连接full join、自连接和自然连接natural join,常用的主要就是内连、外连和交叉连接三种。

有关连接详细介绍可见:
SQL六大连接解析

连接方式示意图如下:

还是简单示例,多几张表规律也不变,这里只创建学生和班级关联的两张表。

故意设置两条冗余数据,没有完全关联,用于体现不同连接方式的查询结果。

here we go

内连查询

内连接又称等值连接,返回两张表共同的部分,用于得到内部共有的数据,如下图所示:

内连查询inner join

关键字inner join,也可写为join,on为关联条件,多表查询时用,逗号分割,默认使用内连查询,即

sql 复制代码
select * from tab_a, tab_b where 条件;
# 等价于
select  *  from  tab_a inner  join  tab_b on 条件;

直接执行

sql 复制代码
SELECT student.`name`,class.class_name FROM student inner join class ;

显示如下:

缺少关联条件on时,内连查询会退化为交叉查询,结果组合为笛卡尔积的形式返回。

补充:name属于 MySQL 潜在关键字 / 常用内置词,为避免解析混淆,建议用`包围

关联条件 on

使用关联条件进行限定的完整sql语句如下:

sql 复制代码
SELECT student.`name`,class.class_name 
FROM student inner join class 
# 匹配关联规则
on student.class_id=class.class_id;
# 过滤条件仍然使用 where 

此时可正常展示交集的三条数据:

外连查询

外连接是将本表与外部表组合到一起,连接外部,具体可分为左外连接、右外连接,全连接。

左外连接

左外连接left join=left outer join,是以左侧表为准,连接外部,即:

示例语句:

sql 复制代码
SELECT student.`name`,class.class_name 
FROM student left join class 
on student.class_id=class.class_id;

输出结果如下:

右外连接

右外连接则完全相反,保留右表全部数据,左侧没有的数据置为空,这里不重复展示。

全连接

全连接结合左、右外连接的结果,使用NULL值作为两侧缺失匹配结果,示意图如下:

要注意的是MySQL中没有full join全连接关键词,要用union结合结果,使用示例如下:\

sql 复制代码
-- 左连接:所有学生 + 匹配的班级
SELECT s.*, c.* 
-- student 别名起为s
FROM student s
LEFT JOIN class c ON s.class_id = c.class_id
UNION
-- 右连接:所有班级 + 匹配的学生(补充左连接中无学生的班级)
SELECT s.*, c.* 
FROM student s
RIGHT JOIN class c ON s.class_id = c.class_id;

形成结果如下:

补充:MySQL中的UNION用于连接两个以上的 SELECT 语句的结果组合到一个结果集合,并去除重复的行,UNION ALL则会保留重复行。

交叉查询

用于生成两张表的笛卡尔积(需要全量组合的场景),左表记录记录与右表每一行的组合,示例语句如下:

sql 复制代码
SELECT *
FROM student
CROSS JOIN class;

形成结果就是内连查询不指定关联条件on时的结果:

生产环境中谨慎使用,生成大量数据,易撑爆服务器。

总结

  • 内连接(INNER JOIN):仅返回两张表满足关联条件的交集,无匹配的行直接过滤;
  • 外连接(LEFT/RIGHT/FULL):以某张表为基准保留全部数据,无匹配的字段填充 NULL;
  • 交叉查询(CROSS JOIN):无关联条件,返回两张表的笛卡尔积(全量组合);

使用方法为:

sql 复制代码
select * from table_A (left/right) join table_B on 关联条件 where 限定条件;
相关推荐
java_logo21 分钟前
Docker 部署 CloudBeaver:轻松搭建网页数据库管理平台
数据库·docker·容器·数据库管理·dbeaver·轩辕镜像·cloudbeaver
李白客2 小时前
AI 数据库落地 NL2SQL:准确率卡在四成,问题在表注释不在模型
数据库
FluxDB2 小时前
FluxDB vs DBX vs DBeaver:GPUI、Tauri、Eclipse 三种技术栈实测
数据库·mysql
杨航 AI2 小时前
JEV的用法
java·前端·数据库
数据库小学妹2 小时前
MySQL分页结果不稳定:唯一键兜底与游标分页
数据库·mysql·dba
风翼靓崽3 小时前
mysql数据备份/恢复
数据库·mysql
贝锐3 小时前
金仓、达梦、TDSQL全适配:向日葵补齐信创数据库层远程运维能力
运维·数据库·信创
xixiaoyunya4 小时前
Redis缓存三大问题实战:穿透、击穿、雪崩,我用一个电商秒杀场景讲清楚
数据库·redis·缓存
这个DBA有点耶5 小时前
Merge还是Materialize?一文讲透MySQL 8.0 CTE底层的执行计划博弈与性能陷阱
数据库·mysql·架构
Thanks_ks6 小时前
MySQL 的 REPEATABLE READ 到底能不能防幻读——从快照读、当前读到 Next-Key Lock
数据库·mysql·innodb·mvcc·锁机制·事务隔离级别·间隙锁