MySQL 视频课 · 50 集 / 组
多表查询练习与本章小结
P48–P50 · 共 3 集 · 每集独立 anchor,可直接从目录跳到本页某一集
视频 p=48 · 时长 17:42
P48 48. 基础-多表查询-练习1
原视频:在 B 站新标签打开(p=48) · 单独打开这一集 →
看视频,对照阅读:在新标签打开原视频(p=48) · 先看跟播对照
这页是练习,题干按视频同主题重写,数据换成上面两张小表,不是原题逐字还原。四道题分别练隐式内连接、显式内连接 + 年龄过滤、有员工的部门、保留无部门员工。原课第 1 题是隐式连接、不带年龄条件;第 2 题是「年龄小于 30 岁」+ 显式内连接。本页题 2 把数字改成 age < 25,是本页自定的,别拿它和原题对答案。
复习模式:快速跳知识点(详解在下方各节)
复习顺序:先看“一句话理解”能否复述,再扫步骤,最后做自测;答不出时回到小例与易错。
一句话理解
把前几页连起来用:先判断“要哪些行”,再选内连接还是外连接,最后检查有没有重复、有没有漏掉无部门的人。
跟播:视频里 ↔ 本站
视频在「5.7 多表查询案例」上逐题写:第 1 题隐式、第 2 题显式 + age<30、第 3 题去重、第 4 题外连接。
| 视频里 / 原课字段 | 本站对应 |
|---|---|
| 讲义 emp 17 行 / dept 6 行 | 本站 employee 4 行 / department 3 行(原创小表) |
| emp.job、emp.entrydate | 本页小表没有这两列,题目里也不问 |
看完应能:看到「显式内连接 + 年龄过滤」能立刻写出 INNER JOIN … ON … WHERE age < 30
看视频时以讲义表为准,跟练时用本站表;结构相同、数字不同。
按这 3 步做
- 逐题先写“表 + 连接条件 + 过滤条件”三行草稿。表是 employee 和 department,连接条件是 e.dept_id = d.id,过滤条件才决定内连接还是外连接。
- 题目说“所有员工,没有部门也要”就选 LEFT JOIN;说“有员工的部门”就用内连接再去重。两类题的外连接方向相反,先抓关键词。
- 写完数行数对答案:4 名员工里 3 人有部门,3 个部门里 2 个有人。题1 和题2 都是内连接,区别是题2 多一个年龄过滤,所以题2 行数更少(1 行对 3 行);两题行集合不同,不能互相对照。
小例
-- 表:department(1 研发部, 2 测试部, 3 运营部)
-- employee:小林22/研发8000/上级2,小周25/研发10000/无上级,小陈30/测试12000/上级2,小李21/无部门/NULL/上级2
-- 建表与插入语句见本页练习脚本 p48.sql(独立练习库,跑一次就有这两张表)
-- 题1:所有员工及其部门(隐式内连接),3 行
SELECT e.name AS 员工, e.age AS 年龄, d.name AS 部门
FROM employee e, department d
WHERE e.dept_id = d.id
ORDER BY e.id;
-- 题2:年龄小于 25 的员工及其部门(显式内连接;25 是本页自定,原课是 age < 30),1 行
SELECT e.name AS 员工, e.age AS 年龄, d.name AS 部门
FROM employee e
INNER JOIN department d ON e.dept_id = d.id
WHERE e.age < 25
ORDER BY e.id;
-- 题3:有员工的部门(内连接 + 去重)
SELECT DISTINCT d.id, d.name
FROM employee e, department d
WHERE e.dept_id = d.id;
-- 题4:所有员工及其部门,没部门也要出现
SELECT e.name AS 员工, e.age AS 年龄, d.name AS 部门
FROM employee e
LEFT JOIN department d ON e.dept_id = d.id
ORDER BY e.id;
题1 是隐式内连接,4 名员工里只有 3 人有部门(小李 dept_id 为空,配不上),得到 3 行:小林、小周、小陈。题2 在本页是「显式内连接 + age < 25」:年龄小于 25 的有小林 22 和小李 21,小李没部门被内连接去掉,所以只剩 1 行小林——这就是题2 比题1 少的原因,两题行集合不同,不能互相对照。题3 得到 2 行:1 研发部、2 测试部;运营部没人所以不出现;DISTINCT 是因为研发部有两名员工,不去重会重复两行。题4 得到 4 行,小李的部门列是 NULL。 题2 里的 age < 25 是过滤员工,放在 WHERE;如果改成左连接再把它挪进 ON,年龄大的员工仍会出现,只是部门为 NULL,行数就多了。说明:题2 是本页自己的原创练习(显式内连接 + age < 25),不是视频原题逐字;原课第 2 题是「年龄小于 30 岁」+ 显式内连接(讲义 p85 第 2 题),第 1 题才是隐式连接且不带年龄条件,别混着对答案。
易错点
- 题3 忘了 DISTINCT,部门会按员工人数重复。
- 题4 “所有员工”却用了内连接,会漏掉小李且不报错。
- 把 e.age 之类的员工过滤写进 ON,左连接仍保留全部员工,含义容易混:连接条件放 ON,过滤员工放 WHERE。
30 秒速记
自测(3 题,先答再展开)
自测 1:为什么题3 要 DISTINCT?
研发部有两名员工,连接后部门行会重复;DISTINCT 按整行去重。
自测 2:题4 若把 LEFT 改成 INNER,结果几行?
3 行,小李因为 dept_id 为 NULL 被丢掉。
自测 3:题4 结果里小李的部门列是什么?
NULL;LEFT JOIN 保留了他,但 department 里没有对应行。
材料与来源
展开材料出处、讲义页码与证据等级
| 材料 | 类型 / 位置 | 支持了什么 |
|---|---|---|
| BV1Kr4y1i7ru P48(平台标题) | 平台视频页 · P48 | 静帧 t=212s 显示原课四道练习(隐式连接、显式连接、有员工的部门、外连接保留无部门员工);t=637s 为第3/4题答案区 |
| MySQL 8.0 Reference Manual — JOIN Clause | 官方文档 | 仅用于核对连接语义与错误码,不是课程材料 |
本集无逐字稿(匿名 player/v2 返回 subtitles=[]、need_login_subtitle=true),依据平台标题、讲义 p85–86「5.7 多表查询案例」与公开静帧核对,属主题级核实。示例表与数据为本笔记自建,不是课程原表;不含原始帧或字幕。 题干按同类题型重写;题2 用 age < 25 + 显式内连接,原课第 2 题是 age < 30 + 显式内连接,本页没有照抄原题。
讲义对照:讲义 5.7 多表查询案例(第 1–4 题所在段) · p85–86(公开镜像;按主题对应,切点 notexact)
- 画面静帧 9 帧,采样点 0:12–17:29 / 全片 17:42(只用于确认画面主题,不作内容边界)
- 原声字幕未取得:匿名接口字幕轨为空且需登录,未使用任何账号
等级含义:平台视频页 / 官方文档 / 课件 = 原始材料;二手整理 = 参考;推断 = 未经核实。站内补充的解释与练习会在此说明。
视频 p=49 · 时长 21:29
P49 49. 基础-多表查询-练习2
原视频:在 B 站新标签打开(p=49) · 单独打开这一集 →
看视频,对照阅读:在新标签打开原视频(p=49) · 先看跟播对照
第二组练习是组合拳:分组统计、相关子查询,再加一条原课的重点形状——按薪资档位(salgrade)做区间连接,然后把部门连上变三表。题干按视频同主题重写,数据仍用本站小表。
复习模式:快速跳知识点(详解在下方各节)
复习顺序:先看“一句话理解”能否复述,再扫步骤,最后做自测;答不出时回到小例与易错。
一句话理解
先把需求拆成单句验证:分组统计、相关子查询各一条;薪资档位用 salgrade 的区间连接,再把部门连上就是三表。
跟播:视频里 ↔ 本站
视频停在「所有员工的工资等级」与「研发部员工及工资等级」两题上,第二题就是三表。
| 视频里 / 原课字段 | 本站对应 |
|---|---|
| 讲义 emp 17 行 × dept 6 行 × salgrade 8 档 | 本站 employee 4 行 × department 3 行 × salgrade 4 档 |
| emp.salary BETWEEN salgrade.losal AND salgrade.hisal | employee.salary BETWEEN salgrade.losal AND salgrade.hisal |
看完应能:能先写出「工资落哪档」,再加一条部门连接变成三表
看视频时以讲义表为准,跟练时用本站表;结构相同、数字不同。
按这 4 步做
- 统计类先定「以谁为基准」。要每个部门都出现(包括没人),就以 department 为左表 LEFT JOIN employee,别反过来。
- 计数时用 COUNT(e.id) 而不是 COUNT(*)。左连接会给没人部门补一行 NULL,COUNT(*) 会把它算成 1 人,COUNT(e.id) 才是 0。
- 相关子查询里外层的值会传进内层。e.salary > (SELECT AVG(x.salary) ... WHERE x.dept_id = e.dept_id) 读作「高于本部门平均」,内层每行重算。
- 查薪资档次不用等值连接:
e.salary BETWEEN s.losal AND s.hisal就是一条非等值连接;要部门名就把 department 再连一次,变成三表。
小例
-- 表:department(1 研发部, 2 测试部, 3 运营部)
-- employee:小林22/研发8000/上级2,小周25/研发10000/无上级,小陈30/测试12000/上级2,小李21/无部门/NULL/上级2
-- 建表与插入语句见本页练习脚本 p49.sql(独立练习库 mysqlnotes_p49,跑一次就有这两张表)
-- 每部门人数与平均工资(运营部也要出现)
SELECT d.name AS 部门, COUNT(e.id) AS 人数, AVG(e.salary) AS 平均工资
FROM department d
LEFT JOIN employee e ON e.dept_id = d.id
GROUP BY d.id, d.name
ORDER BY d.id;
-- 高于本部门平均工资的人(相关子查询)
SELECT e.name AS 员工, e.dept_id AS 部门号, e.salary AS 工资
FROM employee e
WHERE e.salary > (
SELECT AVG(x.salary) FROM employee x WHERE x.dept_id = e.dept_id
);
第一段 3 行:研发部 2 人 / 9000、测试部 1 人 / 12000、运营部 0 人 / NULL。第二段研发部平均 9000,小周 10000 入选;测试部只有小陈,12000 不大于 12000;小李没有部门,内层算不出平均(NULL),不入选。共 1 行。 反连接写法:SELECT d.id, d.name FROM department d LEFT JOIN employee e ON e.dept_id = d.id WHERE e.id IS NULL,结果只有 3 运营部。这三个数字就是核对后面所有统计题的基准,先记住它们。
下面每条只演示一个点,可以单独复制执行。
-- salgrade 是本页原创的 4 档小表(grade, losal, hisal),不是讲义那 8 档
SELECT e.name AS 员工, e.salary AS 工资, s.grade AS 档位
FROM employee e
JOIN salgrade s ON e.salary BETWEEN s.losal AND s.hisal
ORDER BY e.id;
3 行:小林 8000→2 档、小周 10000→3 档、小陈 12000→3 档。BETWEEN 含两端,所以 12000 落在 9001–12000 的第 3 档。小李的 salary 是 NULL,NULL BETWEEN … 得 unknown,连不上任何档,这一行就消失了——非等值连接只保留「真的落进某个区间」的行。
小林 8000 2|小周 10000 3|小陈 12000 3(小李 NULL 不出现)
SELECT e.name AS 员工, d.name AS 部门, s.grade AS 档位
FROM employee e
JOIN department d ON e.dept_id = d.id
JOIN salgrade s ON e.salary BETWEEN s.losal AND s.hisal
ORDER BY e.id;
3 行:小林 研发部 2、小周 研发部 3、小陈 测试部 3。两条连接条件互相独立:一条是等值(dept_id = id),一条是区间(BETWEEN losal AND hisal)。三表不是「一条 ON 写三个表」,而是每连一张表就补一条 ON,顺序按「先等值、后区间」读最清楚。
小林 研发部 2|小周 研发部 3|小陈 测试部 3
易错点
- LEFT JOIN 后用 COUNT(*) 统计人数,会把「没人」的部门算成 1。
- 相关子查询忘写 x.dept_id = e.dept_id,就退化成全公司平均,结果看似合理但是错的。
- 区间连接漏了端点(写成 salary > losal AND salary < hisal),正好等于档位边界的工资会掉档。
- 以为 NULL 工资会落进第 1 档:NULL 参与 BETWEEN 得 unknown,不会匹配任何档。
30 秒速记
自测(3 题,先答再展开)
自测 1:运营部为什么会出现在结果里,人数却是 0?
department 是左表,LEFT JOIN 保留全部部门;COUNT(e.id) 不数补出来的 NULL 行。
自测 2:相关子查询漏写 dept_id = e.dept_id 会怎样?
变成和全公司平均比,结果错但通常不报错。
自测 3:统计每个部门人数为什么不用 COUNT(*)?
LEFT JOIN 补出的 NULL 行也会被 COUNT(*) 计入,没人部门会变成 1。
材料与来源
展开材料出处、讲义页码与证据等级
| 材料 | 类型 / 位置 | 支持了什么 |
|---|---|---|
| BV1Kr4y1i7ru P49(平台标题) | 平台视频页 · P49 | 静帧 t=644s 显示三表连接题目;t=1031s 显示按部门统计人数的子查询写法 |
| MySQL 8.0 Reference Manual — Subqueries | 官方文档 | 仅用于核对子查询语义与错误码,不是课程材料 |
本集无逐字稿(匿名 player/v2 返回 subtitles=[]、need_login_subtitle=true),依据平台标题、讲义 p86「5.7 多表查询案例」第 5–6 题与公开静帧核对:原课用 emp / dept / salgrade 三表,salgrade 是 grade, losal, hisal 三列共 8 档。本站用 employee / department 加一张 4 档原创 salgrade 复现同一形状,表名、行数与档位数字都不同,不能拿本站结果对讲义答案。
讲义对照:讲义 5.7 多表查询案例(第 5–12 题所在段) · p86–88(公开镜像;按主题对应,切点 notexact)
- 画面静帧 9 帧,采样点 0:12–21:16 / 全片 21:29(只用于确认画面主题,不作内容边界)
- 原声字幕未取得:匿名接口字幕轨为空且需登录,未使用任何账号
等级含义:平台视频页 / 官方文档 / 课件 = 原始材料;二手整理 = 参考;推断 = 未经核实。站内补充的解释与练习会在此说明。
视频 p=50 · 时长 4:14
P50 50. 基础-多表查询-小结
原视频:在 B 站新标签打开(p=50) · 单独打开这一集 →
看视频,对照阅读:在新标签打开原视频(p=50)
多表查询收尾:把整章压成三个问题——保留谁、拼列还是接行、要不要嵌套。
这一集在讲什么
多表查询的决策只有三步:先看关系定连接条件,再看要不要保留配不上的行,最后看要不要嵌套。
要点(3 条)
- 关系决定外键位置:一对多外键在多的一方;多对多要中间表;一对一外键加 UNIQUE。
- 连接先问“要不要保留全部”:只留匹配用内连接;保留一侧用左/右外连接;同表两个身份用自连接。
- 结果怎么合:合并行用 UNION(去重)或 UNION ALL;拿内层结果当条件或当表,就按返回形状选标量 / 列 / 行 / 表子查询。
30 秒回忆
想再练一下(2 题,选做)
自测 1:一条查询里怎么同时体现外连接和计数正确?
以保留侧为左表 LEFT JOIN,计数用 COUNT(右表主键)。
自测 2:多对多为什么不能只加一个外键?
两边都是多,外键放哪边都会重复;要用中间表拆成两个一对多。
材料与来源
展开材料出处、讲义页码与证据等级
| 材料 | 类型 / 位置 | 支持了什么 |
|---|---|---|
| BV1Kr4y1i7ru P50(平台标题) | 平台视频页 · P50 | 静帧 t=151s 为“总结”页,列出多表关系、内/外/自连接与四类子查询 |
| MySQL 8.0 Reference Manual — JOIN Clause | 官方文档 | 仅用于核对连接语义与错误码,不是课程材料 |
讲义无“小结”正文;本页参照前节 5.1–5.7 多表查询(p69–88)整理。原声字幕未取得(匿名接口字幕轨为空),讲师逐句讲解未核;本页不含 SQL 示例。
讲义对照:参照前节整理,无独立讲义正文;参照前节 5.1–5.7 多表查询(p69–88)
- 画面静帧 9 帧,采样点 0:12–4:01 / 全片 4:14(只用于确认画面主题,不作内容边界)
- 原声字幕未取得:匿名接口字幕轨为空且需登录,未使用任何账号
等级含义:平台视频页 / 官方文档 / 课件 = 原始材料;二手整理 = 参考;推断 = 未经核实。站内补充的解释与练习会在此说明。