MySQL 视频课 · 50 集 / 多表查询:多表关系、内/外/自连接、联合查询 / P40
第 40 集 / 共 50 · 多表查询:多表关系、内/外/自连接、联合查询 · 视频 p=40 · 时长 7:27
P40 40. 基础-多表查询-外连接
看视频,对照阅读:在新标签打开原视频(p=40) · 先看跟播对照
外连接解决“配不上的行也要留下”的问题。左连接保左表,右连接保右表,另一边补 NULL。
复习模式:快速跳知识点(详解在下方各节)
复习顺序:先看“一句话理解”能否复述,再扫步骤,最后做自测;答不出时回到小例与易错。
一句话理解
外连接在内连接的基础上,保留某一侧“配不上”的行,另一侧补 NULL。
跟播:视频里 ↔ 本站
视频用左、右外连接演示「配不上的行怎么保留」。
| 视频里 / 原课字段 | 本站对应 |
|---|---|
| 讲义里没有部门的是陈友谅(dept_id 为空) | 本站是小李(dept_id 为空),左连接后部门列是 NULL |
| emp LEFT JOIN dept | employee LEFT JOIN department(写法相同) |
看完应能:能解释 LEFT JOIN 出来的 NULL 是「没配上」,不是数据坏了
看视频时以讲义表为准,跟练时用本站表;结构相同、数字不同。
按这 4 步做
- 先想清楚要保住谁。要“所有员工,包括没部门的”,员工在左就用 LEFT JOIN;要“所有部门,包括没人的”,部门放右边用 RIGHT JOIN。
- ON 里写连接条件,也可以写“只影响能不能配上”的过滤。过滤放 ON 还是 WHERE,取决于你想保留哪些左行:想保留全部员工、只给研发部的人标上部门,就把
d.name = '研发部'放 ON,其他员工照样出现、部门列是 NULL;只要研发部员工,就把条件放 WHERE(或者干脆用内连接)。两者是不同的问题,不是对错。判断办法:把条件从 ON 挪到 WHERE,如果连本来没配上的左行也一起消失,说明这个过滤本身在筛员工,不只是筛匹配。 - 验证时数行数:左连接保证左表每一行至少出现一次,所以结果行数不会少于左表行数;本例
department.id是主键、一名员工最多配上一个部门,结果才恰好 4 行。若左表一行配上多个右表行,行数变多(4 行变 5 行以上)是正常放大,不是写错;变成 3 行才说明有左行被过滤掉了。 - 统计时要分清 COUNT(*) 和 COUNT(右表列):前者数结果行,后者只数真正匹配上的行。
小例
-- 表:department(1 研发部, 2 测试部, 3 运营部)
-- employee:小林22/研发8000/上级2,小周25/研发10000/无上级,小陈30/测试12000/上级2,小李21/无部门/NULL/上级2
-- 建表与插入语句见本页练习脚本 p40.sql(独立练习库 mysqlnotes_p40,跑一次就有这两张表)
SELECT e.name AS 员工, d.name AS 部门
FROM employee e
LEFT JOIN department d ON e.dept_id = d.id
ORDER BY e.id;
SELECT e.name AS 员工, d.name AS 部门
FROM employee e
RIGHT JOIN department d ON e.dept_id = d.id
ORDER BY d.id;
左连接 4 行,第 4 行是“小李 / NULL”,因为他的 dept_id 为空;本例 department.id 是主键,一名员工最多配一个部门,所以没有一对多放大,行数才正好等于左表的 4 行。右连接换方向保部门,也是 4 行,最后一行“NULL / 运营部”,因为运营部还没人。想让运营部那行出现在“部门在左”的写法里,把表序换成 department LEFT JOIN employee 即可。 右连接也可以调换表序写成 LEFT JOIN,结果相同;团队里通常统一用 LEFT,方向更一致。
易错点
- LEFT JOIN 后在 WHERE 写 d.id IS NOT NULL 会滤掉 NULL 行,等价于内连接;要专门找“没部门的员工”应写 WHERE d.id IS NULL。
- COUNT(*) 数的是结果行(4),COUNT(d.id) 数的是匹配上的部门(3);统计“多少人有部门”必须用后者。
- MySQL 没有 FULL OUTER JOIN;要两边都保留只能 LEFT UNION RIGHT,并注意去重。
30 秒速记
自测(3 题,先答再展开)
自测 1:左连接后想只留“没有部门的员工”,条件怎么写?
WHERE d.id IS NULL(或 d.name IS NULL),写在连接之后。
自测 2:LEFT JOIN 结果 4 行,COUNT(*) 和 COUNT(d.id) 分别是?
4 和 3;COUNT(列) 不数 NULL。
自测 3:为什么 LEFT JOIN 之后再写 d.id IS NOT NULL 会变回内连接?
它把补出来的 NULL 行全部滤掉,剩下的就是匹配行,结果与内连接相同。
材料与来源
展开材料出处、讲义页码与证据等级
| 材料 | 类型 / 位置 | 支持了什么 |
|---|---|---|
| BV1Kr4y1i7ru P40(平台标题) | 平台视频页 · P40 | 静帧 t=89s 为“连接查询-外连接”标题页;t=178s 显示左外/右外两道题的注释 |
| MySQL 8.0 Reference Manual — JOIN Clause | 官方文档 | 仅用于核对连接语义与错误码,不是课程材料 |
本集无逐字稿(匿名 player/v2 返回 subtitles=[]、need_login_subtitle=true),并以讲义公开镜像讲义 5.4 外连接(p77–78)核对章节与主题;画面静帧只用于确认场景,不是内容边界。示例表与数据为本笔记自建,不是课程原表;不含原始帧或字幕。
讲义对照:讲义 5.4 外连接 · p77–78(公开镜像;按主题对应,切点 notexact)
- 画面静帧 9 帧,采样点 0:12–7:13 / 全片 7:27(只用于确认画面主题,不作内容边界)
- 原声字幕未取得:匿名接口字幕轨为空且需登录,未使用任何账号
等级含义:平台视频页 / 官方文档 / 课件 = 原始材料;二手整理 = 参考;推断 = 未经核实。站内补充的解释与练习会在此说明。