MySQL 视频课 · 50 集 / 组

多表查询:多表关系、内/外/自连接、联合查询

P37–P42 · 共 6 集 · 每集独立 anchor,可直接从目录跳到本页某一集

视频 p=37 · 时长 12:12

P37 37. 基础-多表查询-多表关系介绍

讲义 5.1 多表关系(一对多 / 多对多 / 一对一) p69–72

按主题对应,非逐句切分

来源与核对说明

以同版讲义的公开镜像核对章节与页码(镜像非官方出品);非逐字稿,示例为原创补充。

本页是学习笔记,不等同于视频逐字稿。原声字幕未取得(匿名接口字幕轨为空且需登录,未使用任何账号),也没有逐句讲解记录;讲义只按节与页码对应,切点未逐句确证。

讲义索引:p69–72 · 5.1 多表关系(一对多 / 多对多 / 一对一) · 切点 notexact

讲义是第三方公开镜像(95 页 PDF),不是官方原件;这里只用它核对章节顺序与页码,不转载正文。

完整来源说明与变更记录 →

看视频,对照阅读:在新标签打开原视频(p=37) · 先看跟播对照

先讲清数据:本页用两张小表——department(1 研发部、2 测试部、3 运营部)与 employee 四行(小林 22/研发/8000/上级 2,小周 25/研发/10000/无上级,小陈 30/测试/12000/上级 2,小李 21/无部门/NULL/上级 2)。讲义这一节用的是 emp 17 行 / dept 6 行,2 号部门叫市场部;表名、行数、部门名都不同,结构对应即可,不要对总数。

复习模式:快速跳知识点(详解在下方各节)

复习顺序:先看“一句话理解”能否复述,再扫步骤,最后做自测;答不出时回到小例与易错。

一句话理解

表之间的关系就三种:一对一、一对多、多对多。判断方法很实在——看外键放在哪张表、要不要第三张中间表。

按这 4 步做

  1. 先数“谁多”。一个部门有多名员工,一名员工只属于一个部门,所以 employee 是“多”的一方,外键 dept_id 放这里。为什么:外键放多的一方,每条员工记录只能填一个部门号,重复是天然的。
  2. 一对一用于拆表。比如员工表和员工档案表,两边都只对应一条;外键放任意一方,但要加 UNIQUE,否则会退化成一堆一对多。
  3. 多对多必须建中间表。学生选课,一个学生选多门课,一门课被多人选;中间表放 student_id、course_id 两个外键,联合起来当主键,重复选课才插不进去。
  4. 关系定完再写查询。一对多靠 dept_id = id 连两张表;多对多要连三张表;一对一多一次 join。连接条件不是猜的,是外键指出来的。

小例

先准备本集练习数据:p37.sql · 练习库说明

SQL 示例
-- 本页练习用的建表段:在 mysqlnotes_p37 里执行一次(后面各页用各自的 pNN.sql,不复用这里)
-- department(1 研发部, 2 测试部, 3 运营部)
-- employee:小林22/研发8000/上级2,小周25/研发10000/无上级,小陈30/测试12000/上级2,小李21/无部门/NULL/上级2

CREATE TABLE department (
  id INT PRIMARY KEY,
  name VARCHAR(20) NOT NULL
);
CREATE TABLE employee (
  id INT PRIMARY KEY,
  name VARCHAR(20) NOT NULL,
  age INT,
  dept_id INT,
  salary INT,
  manager_id INT
);
INSERT INTO department VALUES (1,'研发部'),(2,'测试部'),(3,'运营部');
INSERT INTO employee VALUES
 (1,'小林',22,1,8000,2),
 (2,'小周',25,1,10000,NULL),
 (3,'小陈',30,2,12000,2),
 (4,'小李',21,NULL,NULL,2);

-- 一对多:外键放在“多”的一方
ALTER TABLE employee
  ADD CONSTRAINT fk_emp_dept
  FOREIGN KEY (dept_id) REFERENCES department(id);

前面几段只建表灌数据;这两张表属于本页练习库 mysqlnotes_p37,后面各页用的是各自的 pNN.sql,列数和数据类型可能不同,别拿这里的 6 列结构去套别的页。最后一段给 employee.dept_id 加外键:以后 dept_id 只能填 1、2、3 或 NULL,写 99 会被拒绝。自检跑 SELECT id,name,dept_id FROM employee ORDER BY id,应得 4 行,小李的 dept_id 是 NULL——外键允许空值,不代表他有部门。

易错点

  • 外键方向写反(在 department 里放 employee_id),一个部门只能记一个员工,一对多就装不下了。
  • 多对多只在一边加外键,另一边的对应关系无处存放,迟早出现重复行。
  • 外键列类型必须和被引用主键一致(INT 对 INT),类型不同建约束会失败。

30 秒速记

一对多:外键在多的一方;一对一:外键+UNIQUE;多对多:中间表两个外键;连接条件来自外键。

自测(2 题,先答再展开)

自测 1:一个部门多名员工,外键该放哪张表?

employee(多的一方),存 dept_id 指向 department.id;放反了一个部门只能挂一个员工。

自测 2:多对多的中间表为什么常把两个外键做成联合主键?

防止同一对组合重复插入,同时天然形成“两个一对多”。

材料与来源

展开材料出处、讲义页码与证据等级
材料类型 / 位置支持了什么
BV1Kr4y1i7ru P37(平台标题)平台视频页 · P37静帧 t=292s 显示“学生-课程”多对多与中间表两个外键;t=219s 为本节标题页
MySQL 8.0 Reference Manual — JOIN Clause官方文档仅用于核对连接语义与错误码,不是课程材料

本集无逐字稿(匿名 player/v2 返回 subtitles=[]、need_login_subtitle=true),依据平台标题、讲义 p69–72「5.1 多表关系」与公开静帧核对;多对多部分以 t≈292s 静帧(中间表)为准。一对一、一对多的表述为同主题通用整理。示例表与数据为本笔记自建,不是课程原表。

讲义对照:讲义 5.1 多表关系(一对多 / 多对多 / 一对一) · p69–72(公开镜像;按主题对应,切点 notexact)

  • 画面静帧 9 帧,采样点 0:12–11:59 / 全片 12:12(只用于确认画面主题,不作内容边界)
  • 原声字幕未取得:匿名接口字幕轨为空且需登录,未使用任何账号

等级含义:平台视频页 / 官方文档 / 课件 = 原始材料;二手整理 = 参考;推断 = 未经核实。站内补充的解释与练习会在此说明。

视频 p=38 · 时长 8:04

P38 38. 基础-多表查询-概述

讲义 5.2 多表查询概述(含 5.2.1 数据准备) p72–75

按主题对应,非逐句切分

来源与核对说明

以同版讲义的公开镜像核对章节与页码(镜像非官方出品);非逐字稿,示例为原创补充。

本页是学习笔记,不等同于视频逐字稿。原声字幕未取得(匿名接口字幕轨为空且需登录,未使用任何账号),也没有逐句讲解记录;讲义只按节与页码对应,切点未逐句确证。

讲义索引:p72–75 · 5.2 多表查询概述(含 5.2.1 数据准备) · 切点 notexact

讲义是第三方公开镜像(95 页 PDF),不是官方原件;这里只用它核对章节顺序与页码,不转载正文。

完整来源说明与变更记录 →

看视频,对照阅读:在新标签打开原视频(p=38) · 先看跟播对照

两张表放一起查,最容易出的错不是语法,而是忘写连接条件。本页先把“为什么会多出一堆行”讲清楚。

复习模式:快速跳知识点(详解在下方各节)

复习顺序:先看“一句话理解”能否复述,再扫步骤,最后做自测;答不出时回到小例与易错。

一句话理解

多表查询就是把两张表放在一起查。不写连接条件,MySQL 会把每行都和对方每行配一次,得到笛卡尔积——大部分行没有意义。

按这 4 步做

  1. 先看两张表各自的规模。4 名员工 × 3 个部门 = 12 行,这就是不加条件的全部组合;行数相乘是判断“有没有漏写条件”的最快信号。
  2. 再用连接条件筛掉乱配的行。员工表的 dept_id 和部门表的 id 相等,才说明这名员工属于这个部门,12 行立刻剩 3 行。
  3. 连接条件写在 WHERE(隐式)或 ON(显式)都行,效果一样;差别在可读性,以及外连接时条件必须放 ON。
  4. 最后记住分类:内连接、外连接、自连接、子查询。前三个是“怎么把表拼起来”,子查询是“先算一个结果再用”。

小例

先准备本集练习数据:p38.sql · 练习库说明

SQL 示例
-- 表:department(1 研发部, 2 测试部, 3 运营部)
-- employee:小林22/研发8000/上级2,小周25/研发10000/无上级,小陈30/测试12000/上级2,小李21/无部门/NULL/上级2
-- 建表与插入语句见本页练习脚本 p38.sql(独立练习库 mysqlnotes_p38,跑一次就有这两张表)

-- 故意不写连接条件:4 × 3 = 12 行
SELECT e.name AS 员工, d.name AS 部门
FROM employee e, department d;

-- 补上连接条件:只剩 3 行
SELECT e.name AS 员工, d.name AS 部门
FROM employee e, department d
WHERE e.dept_id = d.id;

第一条返回 12 行,小林会分别配上研发部、测试部、运营部,明显是错配。第二条只剩 3 行:小林-研发部、小周-研发部、小陈-测试部。小李的 dept_id 是 NULL,NULL = 任何值都不成立,所以他不出现——这是内连接的正常行为,不是丢数据。

易错点

  • 只写 FROM a, b 忘写 WHERE,结果行数突然变成两表行数之积;先数行数,再找条件。
  • 想把无部门的员工也留下,却仍在用 WHERE 内连接,做不到;要改用 LEFT JOIN。
  • 两表有同名列(都叫 name)时不用别名区分,会报 column ambiguous。

30 秒速记

多表=先组合再筛选;不写条件=笛卡尔积;连接条件把 4×3 变 3;内连接丢掉不匹配行。

自测(2 题,先答再展开)

自测 1:4 行员工、3 行部门,不写连接条件返回几行?

12 行,行数相乘;写了 dept_id = id 后是 3 行。

自测 2:小李为什么不出现在内连接结果里?

他的 dept_id 是 NULL,与任何 id 比较都不为真,匹配不上;要保留他用 LEFT JOIN。

材料与来源

展开材料出处、讲义页码与证据等级
材料类型 / 位置支持了什么
BV1Kr4y1i7ru P38(平台标题)平台视频页 · P38静帧 t=193s 为“多表查询概述/笛卡尔积”幻灯片;t=471s 列出连接查询分类
MySQL 8.0 Reference Manual — JOIN Clause官方文档仅用于核对连接语义与错误码,不是课程材料

本集无逐字稿(匿名 player/v2 返回 subtitles=[]、need_login_subtitle=true),并以讲义公开镜像讲义 5.2 多表查询概述(p72–75)核对章节与主题;画面静帧只用于确认场景,不是内容边界。示例表与数据为本笔记自建,不是课程原表;不含原始帧或字幕。

讲义对照:讲义 5.2 多表查询概述(含 5.2.1 数据准备) · p72–75(公开镜像;按主题对应,切点 notexact)

  • 画面静帧 9 帧,采样点 0:12–7:51 / 全片 8:04(只用于确认画面主题,不作内容边界)
  • 原声字幕未取得:匿名接口字幕轨为空且需登录,未使用任何账号

等级含义:平台视频页 / 官方文档 / 课件 = 原始材料;二手整理 = 参考;推断 = 未经核实。站内补充的解释与练习会在此说明。

视频 p=39 · 时长 8:15

P39 39. 基础-多表查询-内连接

讲义 5.3 内连接 p75–77

按主题对应,非逐句切分

来源与核对说明

以同版讲义的公开镜像核对章节与页码(镜像非官方出品);非逐字稿,示例为原创补充。

本页是学习笔记,不等同于视频逐字稿。原声字幕未取得(匿名接口字幕轨为空且需登录,未使用任何账号),也没有逐句讲解记录;讲义只按节与页码对应,切点未逐句确证。

讲义索引:p75–77 · 5.3 内连接 · 切点 notexact

讲义是第三方公开镜像(95 页 PDF),不是官方原件;这里只用它核对章节顺序与页码,不转载正文。

完整来源说明与变更记录 →

看视频,对照阅读:在新标签打开原视频(p=39) · 先看跟播对照

内连接是多表查询的主力:只保留两张表能对上的行。写法有两种,结果完全一样,选一种顺手的坚持下去。

复习模式:快速跳知识点(详解在下方各节)

复习顺序:先看“一句话理解”能否复述,再扫步骤,最后做自测;答不出时回到小例与易错。

一句话理解

内连接只保留两张表能对上的行:员工有部门才出现,部门有员工才出现。

按这 4 步做

  1. 先确定连接条件:employee.dept_id = department.id。这是“员工属于哪个部门”的唯一依据,条件写错会得到看似正常其实错位的结果。
  2. 隐式写法把两张表用逗号并列,条件放 WHERE。老教材和简写常用,表一多就容易漏条件。
  3. 显式写法用 INNER JOIN ... ON,连接条件和过滤条件分家。推荐这种:ON 只写“怎么对上”,WHERE 只写“要哪些行”,读起来不容易混。
  4. 写完对一下行数。4 名员工里只有 3 人有部门,内连接就该是 3 行;多出来通常是漏了条件,少了则要查 dept_id 是否为空。另外,ON 里别写 e.age < 30 这类过滤——内连接结果一样,换成外连接就会保留不该保留的行。

小例

先准备本集练习数据:p39.sql · 练习库说明

SQL 示例
-- 表:department(1 研发部, 2 测试部, 3 运营部)
-- employee:小林22/研发8000/上级2,小周25/研发10000/无上级,小陈30/测试12000/上级2,小李21/无部门/NULL/上级2
-- 建表与插入语句见本页练习脚本 p39.sql(独立练习库 mysqlnotes_p39,跑一次就有这两张表)

SELECT e.name AS 员工, e.age AS 年龄, d.name AS 部门
FROM employee e
INNER JOIN department d ON e.dept_id = d.id
ORDER BY e.id;

返回 3 行:小林 22 研发部、小周 25 研发部、小陈 30 测试部。ON 负责把 dept_id 和 id 对上;ORDER BY e.id 只是让结果顺序稳定。把 INNER JOIN 换成“employee e, department d WHERE e.dept_id = d.id”,输出一模一样。 去掉 ORDER BY 再跑,行序可能变,但行集合不变:排序只影响展示。

易错点

  • ON 写成 e.dept_id = d.name,类型和含义都错,却不一定报错,只会得到空结果或错配。
  • 把过滤条件写进 ON 而不是 WHERE,在内连接里结果相同,但换成外连接含义就变了,别养成习惯。
  • SELECT * 会带出两张表的全部列,同名列看起来重复;初学先显式写字段。
  • 给表起了别名后,就不能再用原表名指字段:SELECT e.name … FROM employee e 里写 employee.name 会报 Unknown column。

30 秒速记

内连接=交集;隐式逗号+WHERE,显式 JOIN+ON;匹配不上的行直接消失。

自测(3 题,先答再展开)

自测 1:内连接和外连接最根本的区别?

内连接丢弃匹配不上的行;外连接保留某一侧全部行,另一侧用 NULL 补。

自测 2:两种内连接写法结果会不同吗?

不会,结果相同,只是条件位置和可读性不同。

自测 3:内连接会不会返回重复行?

会;一对多时一条左表记录匹配多行就会重复,需要按业务去重或聚合。

材料与来源

展开材料出处、讲义页码与证据等级
材料类型 / 位置支持了什么
BV1Kr4y1i7ru P39(平台标题)平台视频页 · P39静帧 t=98s 为“连接查询-内连接”标题页;具体 SQL 演示画面不清晰,示例为本笔记自写
MySQL 8.0 Reference Manual — JOIN Clause官方文档仅用于核对连接语义与错误码,不是课程材料

本集无逐字稿(匿名 player/v2 返回 subtitles=[]、need_login_subtitle=true),并以讲义公开镜像讲义 5.3 内连接(p75–77)核对章节与主题;画面静帧只用于确认场景,不是内容边界。示例表与数据为本笔记自建,不是课程原表;不含原始帧或字幕。

讲义对照:讲义 5.3 内连接 · p75–77(公开镜像;按主题对应,切点 notexact)

  • 画面静帧 9 帧,采样点 0:12–8:02 / 全片 8:15(只用于确认画面主题,不作内容边界)
  • 原声字幕未取得:匿名接口字幕轨为空且需登录,未使用任何账号

等级含义:平台视频页 / 官方文档 / 课件 = 原始材料;二手整理 = 参考;推断 = 未经核实。站内补充的解释与练习会在此说明。

视频 p=40 · 时长 7:27

P40 40. 基础-多表查询-外连接

讲义 5.4 外连接 p77–78

按主题对应,非逐句切分

来源与核对说明

以同版讲义的公开镜像核对章节与页码(镜像非官方出品);非逐字稿,示例为原创补充。

本页是学习笔记,不等同于视频逐字稿。原声字幕未取得(匿名接口字幕轨为空且需登录,未使用任何账号),也没有逐句讲解记录;讲义只按节与页码对应,切点未逐句确证。

讲义索引:p77–78 · 5.4 外连接 · 切点 notexact

讲义是第三方公开镜像(95 页 PDF),不是官方原件;这里只用它核对章节顺序与页码,不转载正文。

完整来源说明与变更记录 →

看视频,对照阅读:在新标签打开原视频(p=40) · 先看跟播对照

外连接解决“配不上的行也要留下”的问题。左连接保左表,右连接保右表,另一边补 NULL。

复习模式:快速跳知识点(详解在下方各节)

复习顺序:先看“一句话理解”能否复述,再扫步骤,最后做自测;答不出时回到小例与易错。

一句话理解

外连接在内连接的基础上,保留某一侧“配不上”的行,另一侧补 NULL。

按这 4 步做

  1. 先想清楚要保住谁。要“所有员工,包括没部门的”,员工在左就用 LEFT JOIN;要“所有部门,包括没人的”,部门放右边用 RIGHT JOIN。
  2. ON 里写连接条件,也可以写“只影响能不能配上”的过滤。过滤放 ON 还是 WHERE,取决于你想保留哪些左行:想保留全部员工、只给研发部的人标上部门,就把 d.name = '研发部' 放 ON,其他员工照样出现、部门列是 NULL;只要研发部员工,就把条件放 WHERE(或者干脆用内连接)。两者是不同的问题,不是对错。判断办法:把条件从 ON 挪到 WHERE,如果连本来没配上的左行也一起消失,说明这个过滤本身在筛员工,不只是筛匹配。
  3. 验证时数行数:左连接保证左表每一行至少出现一次,所以结果行数不会少于左表行数;本例 department.id 是主键、一名员工最多配上一个部门,结果才恰好 4 行。若左表一行配上多个右表行,行数变多(4 行变 5 行以上)是正常放大,不是写错;变成 3 行才说明有左行被过滤掉了。
  4. 统计时要分清 COUNT(*) 和 COUNT(右表列):前者数结果行,后者只数真正匹配上的行。

小例

先准备本集练习数据:p40.sql · 练习库说明

SQL 示例
-- 表: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 秒速记

左保左、右保右;配不上补 NULL;过滤放 ON 还是 WHERE 看要保留哪些左行;COUNT(*)≠COUNT(右表列)。

自测(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(只用于确认画面主题,不作内容边界)
  • 原声字幕未取得:匿名接口字幕轨为空且需登录,未使用任何账号

等级含义:平台视频页 / 官方文档 / 课件 = 原始材料;二手整理 = 参考;推断 = 未经核实。站内补充的解释与练习会在此说明。

视频 p=41 · 时长 8:30

P41 41. 基础-多表查询-自连接

讲义 5.5.1 自连接查询 p78–79

按主题对应,非逐句切分

来源与核对说明

以同版讲义的公开镜像核对章节与页码(镜像非官方出品);非逐字稿,示例为原创补充。

本页是学习笔记,不等同于视频逐字稿。原声字幕未取得(匿名接口字幕轨为空且需登录,未使用任何账号),也没有逐句讲解记录;讲义只按节与页码对应,切点未逐句确证。

讲义索引:p78–79 · 5.5.1 自连接查询 · 切点 notexact

讲义是第三方公开镜像(95 页 PDF),不是官方原件;这里只用它核对章节顺序与页码,不转载正文。

完整来源说明与变更记录 →

看视频,对照阅读:在新标签打开原视频(p=41) · 先看跟播对照

自连接不涉及第二张表,难点全在“同一张表怎么分身份”。两个别名一给,事情就简单了。

复习模式:快速跳知识点(详解在下方各节)

复习顺序:先看“一句话理解”能否复述,再扫步骤,最后做自测;答不出时回到小例与易错。

一句话理解

自连接就是一张表当两张用:给同一张表起两个别名,一个当员工、一个当上级,再按 manager_id = id 连起来。

按这 4 步做

  1. 先给同一张表两个身份。e 代表“我”,m 代表“我的上级”;不给别名,MySQL 分不清你要哪一行。 别名起得有含义(e 员工、m 上级),比 a、b 好排查。
  2. 连接条件是 e.manager_id = m.id,即“我的上级编号 = 对方的员工编号”。这跟普通两表连接没区别,只是两张表恰好同名。
  3. 顶层老板没有上级,manager_id 是 NULL。要把他留在结果里就用 LEFT JOIN;用内连接他会消失,看起来像“少了个人”。
  4. 字段一律带别名前缀。同名列(两张表都叫 name、id)不带前缀会报 ambiguous,带上就清楚了。

小例

先准备本集练习数据:p41.sql · 练习库说明

SQL 示例
-- 表:department(1 研发部, 2 测试部, 3 运营部)
-- employee:小林22/研发8000/上级2,小周25/研发10000/无上级,小陈30/测试12000/上级2,小李21/无部门/NULL/上级2
-- 建表与插入语句见本页练习脚本 p41.sql(独立练习库 mysqlnotes_p41,跑一次就有这两张表)

SELECT e.name AS 员工, m.name AS 上级
FROM employee e
LEFT JOIN employee m ON e.manager_id = m.id
ORDER BY e.id;

4 行:小林-小周、小周-NULL、小陈-小周、小李-小周。小周是老板,manager_id 为空,所以上级列是 NULL。把 LEFT 改成 INNER,只剩 3 行,小周整行不见——这是自连接最容易踩的坑。 把 ON 改成 e.id = m.manager_id,方向就反过来了,查的是“我的下属”,别名含义要跟着改。

易错点

  • 两个别名写成同一个、或干脆不起别名,会报表名重复 / 字段 ambiguous。
  • 用内连接查“所有员工及其上级”会漏掉没有上级的人;要全量必须 LEFT JOIN。
  • 把 manager_id 理解成“部门编号”之类的别的字段,连接条件一错,结果会很整齐地错。

30 秒速记

自连接=同表两别名;e.manager_id=m.id;老板上级是 NULL;要全量用 LEFT JOIN。

自测(3 题,先答再展开)

自测 1:自连接必须做什么?

给同一张表起两个不同别名,并用别名区分字段。

自测 2:查“所有员工+上级”,内连接会少谁?

少没有上级的人(如小周),因为 manager_id 为 NULL 匹配不上。

自测 3:自连接的两个别名可以互换吗?

可以,但连接条件和字段含义要一起换;互换后查的是“我的下属”而不是“我的上级”。

材料与来源

展开材料出处、讲义页码与证据等级
材料类型 / 位置支持了什么
BV1Kr4y1i7ru P41(平台标题)平台视频页 · P41静帧 t=254s 显示 SELECT * FROM employee a LEFT JOIN employee b ON a.managerid=b.id 的自连接写法
MySQL 8.0 Reference Manual — JOIN Clause官方文档仅用于核对连接语义与错误码,不是课程材料

本集无逐字稿(匿名 player/v2 返回 subtitles=[]、need_login_subtitle=true),并以讲义公开镜像讲义 5.5.1 自连接查询(p78–79)核对章节与主题;画面静帧只用于确认场景,不是内容边界。示例表与数据为本笔记自建,不是课程原表;不含原始帧或字幕。

讲义对照:讲义 5.5.1 自连接查询 · p78–79(公开镜像;按主题对应,切点 notexact)

  • 画面静帧 9 帧,采样点 0:12–8:17 / 全片 8:30(只用于确认画面主题,不作内容边界)
  • 原声字幕未取得:匿名接口字幕轨为空且需登录,未使用任何账号

等级含义:平台视频页 / 官方文档 / 课件 = 原始材料;二手整理 = 参考;推断 = 未经核实。站内补充的解释与练习会在此说明。

视频 p=42 · 时长 5:48

P42 42. 基础-多表查询-联合查询union

讲义 5.5.2 联合查询 p79–80

按主题对应,非逐句切分

来源与核对说明

以同版讲义的公开镜像核对章节与页码(镜像非官方出品);非逐字稿,示例为原创补充。

本页是学习笔记,不等同于视频逐字稿。原声字幕未取得(匿名接口字幕轨为空且需登录,未使用任何账号),也没有逐句讲解记录;讲义只按节与页码对应,切点未逐句确证。

讲义索引:p79–80 · 5.5.2 联合查询 · 切点 notexact

讲义是第三方公开镜像(95 页 PDF),不是官方原件;这里只用它核对章节顺序与页码,不转载正文。

完整来源说明与变更记录 →

看视频,对照阅读:在新标签打开原视频(p=42) · 先看跟播对照

这一页只记一句话:连接横向拼列,UNION 纵向接行。剩下的都是这句的推论。

复习模式:快速跳知识点(详解在下方各节)

复习顺序:先看“一句话理解”能否复述,再扫步骤,最后做自测;答不出时回到小例与易错。

一句话理解

连接横向拼列,UNION 纵向接行。UNION 去重,UNION ALL 不去重、更快。

按这 4 步做

  1. 先保证两条 SELECT 列数一样、对应列类型能相容。列数不同直接报错(ERROR 1222),类型不相容会隐式转换或丢精度。 比如 INT 和 VARCHAR 合并,MySQL 会先转成同一类型再比,结果可能出乎意料。
  2. 要“合并后不重复”用 UNION:它把完全相同的整行去掉,代价是多一次去重。
  3. 确定不会有重复、或就是要保留重复(比如两批统计各自的行)用 UNION ALL,省掉去重开销。
  4. ORDER BY 写在最后一条 SELECT 之后,作用于整个合并结果;只给第一条写排序没有意义。

小例

先准备本集练习数据:p42.sql · 练习库说明

SQL 示例
-- 表:department(1 研发部, 2 测试部, 3 运营部)
-- employee:小林22/研发8000/上级2,小周25/研发10000/无上级,小陈30/测试12000/上级2,小李21/无部门/NULL/上级2
-- 建表与插入语句见本页练习脚本 p42.sql(独立练习库 mysqlnotes_p42,跑一次就有这两张表)

-- 去重:小周只留一次
SELECT name FROM employee WHERE age >= 25
UNION
SELECT name FROM employee WHERE dept_id = 1;

-- 保留重复:小周出现两次
SELECT name FROM employee WHERE age >= 25
UNION ALL
SELECT name FROM employee WHERE dept_id = 1;

第一段左边是小周、小陈,右边是小林、小周;UNION 去掉重复的小周,3 行。第二段同样的数据用 UNION ALL,4 行,小周出现两次。判断重复的依据是“整行完全相同”,不是只看某一列。 列名取第一条 SELECT 的别名,第二条写什么别名都不影响输出表头。

易错点

  • UNION 只去“整行重复”;两行只要有一列不同就都保留。
  • 两边列数不等报 ERROR 1222;用 SELECT * 时表结构一变就可能踩到,明确写列名。
  • 拿 UNION 去拼含义不同的列(比如员工名接部门名),语义会乱;横向关联用 JOIN。
  • UNION 的列名只认第一条 SELECT,第二条的别名不会生效,别指望它改表头。

30 秒速记

UNION 纵接行、去重;UNION ALL 保留重复;列数列型要对齐;ORDER BY 放最后。

自测(3 题,先答再展开)

自测 1:UNION 和 UNION ALL 的区别?

UNION 对合并结果去重,UNION ALL 原样保留所有行、开销更小。

自测 2:两条 SELECT 列数不同会怎样?

报 ERROR 1222,UNION 要求列数一致、类型相容。

自测 3:两条 SELECT 的列顺序不同能 UNION 吗?

能执行,但会按位置硬拼,A 的姓名接到 B 的部门上,语义就错了;列顺序必须人工对齐。

材料与来源

展开材料出处、讲义页码与证据等级
材料类型 / 位置支持了什么
BV1Kr4y1i7ru P42(平台标题)平台视频页 · P42静帧 t=243s 显示 UNION ALL 与 UNION 两段示例;t=335s 为 union / union all 规则页
MySQL 8.0 Reference Manual — UNION官方文档仅用于核对 UNION 去重与列数要求,不是课程材料

本集无逐字稿(匿名 player/v2 返回 subtitles=[]、need_login_subtitle=true),并以讲义公开镜像讲义 5.5.2 联合查询(p79–80)核对章节与主题;画面静帧只用于确认场景,不是内容边界。示例表与数据为本笔记自建,不是课程原表;不含原始帧或字幕。

讲义对照:讲义 5.5.2 联合查询 · p79–80(公开镜像;按主题对应,切点 notexact)

  • 画面静帧 9 帧,采样点 0:12–5:35 / 全片 5:48(只用于确认画面主题,不作内容边界)
  • 原声字幕未取得:匿名接口字幕轨为空且需登录,未使用任何账号

等级含义:平台视频页 / 官方文档 / 课件 = 原始材料;二手整理 = 参考;推断 = 未经核实。站内补充的解释与练习会在此说明。