MySQL 视频课 · 50 集 / 子查询:标量、列、行、表子查询 / P45
第 45 集 / 共 50 · 子查询:标量、列、行、表子查询 · 视频 p=45 · 时长 10:11
P45 45. 基础-多表查询-列子查询
看视频,对照阅读:在新标签打开原视频(p=45) · 先看跟播对照
列子查询返回一列多行,等于给你一个集合。既然是一堆值,就不能再用 = 硬接。
复习模式:快速跳知识点(详解在下方各节)
复习顺序:先看“一句话理解”能否复述,再扫步骤,最后做自测;答不出时回到小例与易错。
一句话理解
列子查询返回一列多行,等于给你一个集合:在集合里挑值用 IN,拿一个值和整个集合逐个比用 ANY / ALL。
跟播:视频里 ↔ 本站
视频停在列子查询的操作符表(IN / NOT IN / ANY / SOME / ALL),并用研发部、财务部对照 > ANY 与 > ALL。
| 视频里 / 原课字段 | 本站对应 |
|---|---|
| emp.salary / emp.dept_id(17 行) | employee.salary / employee.dept_id(4 行) |
| 研发部 = dept_id 1(讲义 dept 6 行) | 研发部 = dept_id 1(本站 department 3 行) |
看完应能:看到 > any 能马上换成「大于最小值」,并知道 SOME 就是 ANY
看视频时以讲义表为准,跟练时用本站表;结构相同、数字不同。
按这 4 步做
- 先确认内层只查一列。多查一列就变成表子查询,IN 接不住;一列多行意味着结果可能是 0 行、1 行或很多行。
- IN 判断「在不在这个集合里」,最常用;NOT IN 是它的反面,但集合里有 NULL 时整体变成 unknown,结果常常是 0 行。
- ANY(与 SOME 完全同义)是「至少有一个满足」:研发部工资是 8000、10000,salary > ANY(那个子查询)只要大于 8000 就成立,也就是大于集合里的最小值。
- ALL 是「全部都满足」:同一份数据里 salary > ALL(那个子查询)要大于 10000,也就是大于集合里的最大值。写完用行数反推,别只看语法。
小例
-- 表:department(1 研发部, 2 测试部, 3 运营部)
-- employee:小林22/研发8000/上级2,小周25/研发10000/无上级,小陈30/测试12000/上级2,小李21/无部门/NULL/上级2
-- 建表与插入语句见本页练习脚本 p45.sql(独立练习库 mysqlnotes_p45,跑一次就有这两张表)
-- IN:研发部和测试部的员工
SELECT name AS 员工, dept_id AS 部门号
FROM employee
WHERE dept_id IN (
SELECT id FROM department WHERE name IN ('研发部','测试部')
);
-- ALL:比研发部所有人都高(= 大于最大值)
SELECT name AS 员工, salary AS 工资
FROM employee
WHERE salary > ALL (
SELECT salary FROM employee WHERE dept_id = 1
);
-- ANY:比研发部“任意一人”工资高即可(= 大于最小值)
SELECT name AS 员工, salary AS 工资
FROM employee
WHERE salary > ANY (
SELECT salary FROM employee WHERE dept_id = 1
)
ORDER BY id;
第一段内层返回 1、2 两个部门号,外层 3 行:小林、小周、小陈。第二段研发部工资是 8000、10000,> ALL 要大于 10000,只剩小陈 12000(1 行)。第三段 > ANY 只要大于 8000 就成立,小周 10000、小陈 12000 都入选(2 行)——同一份数据,ALL 与 ANY 的差别就是「全部」还是「任意一个」。记住方向:> ANY ≡ > MIN,> ALL ≡ > MAX;反过来 < ANY ≡ < MAX,< ALL ≡ < MIN。ALL 的好处是不用自己先想到 MAX,语义直接;ANY 的好处是「比其中任意一个高」这种需求能直说。
下面每条只演示一个点,可以单独复制执行。
-- 集合 {3000, 6000, 9000}:5000 比最小的大、比最大的小
SELECT 5000 > ANY (SELECT 3000 UNION SELECT 6000 UNION SELECT 9000) AS 比任意一个大,
5000 > ALL (SELECT 3000 UNION SELECT 6000 UNION SELECT 9000) AS 比全部都大;
结果一行:1、0。ANY 只要有一个成立就为真,门槛是最小值 3000;ALL 要求全都成立,门槛是最大值 9000。SOME 与 ANY 完全同义,写哪个都行。
1、0(比任意一个大 = 1;比全部都大 = 0)
空集与 NULL:两个反直觉结果(点开再看,不影响主线)
子查询为空集时:> ALL 恒为真(会返回外层所有行),> ANY 恒为假(0 行)。集合里有 NULL 时:> ALL 因为有一个 unknown 而永远不成立;> ANY 只要有一个非 NULL 比较成立就仍为真。下面这条在 MySQL 8.0.46 实测:all_empty=1、any_empty=0,两个与 NULL 比较的结果都是 unknown(IS NULL 为 1)。
SELECT (1 > ALL (SELECT salary FROM employee WHERE 1 = 0)) AS all_empty,
(1 > ANY (SELECT salary FROM employee WHERE 1 = 0)) AS any_empty,
((5 > ALL (SELECT NULL)) IS NULL) AS all_null_unknown;
易错点
- NOT IN 的子查询结果含 NULL 时,整个条件永远不为真,结果 0 行;要么子查询加 WHERE dept_id IS NOT NULL,要么改用 NOT EXISTS。
- IN 后面的子查询只能返回一列;返回两列会报错,需要改成整行比较。
- 把 > ALL 读成「大于其中某一个」就全错了,那是 ANY 的语义;ALL 是「全部都要满足」。
- 以为 ANY 遇空集会全选:空集时 ANY 恒假(0 行),ALL 反而恒真。
30 秒速记
自测(3 题,先答再展开)
自测 1:NOT IN 子查询里有 NULL 会怎样?
比较结果变 unknown,条件不成立,通常返回 0 行;先排除 NULL 或改 NOT EXISTS。
自测 2:salary > ALL(子查询返回 8000、10000)等价于什么?
salary > 10000,即大于集合最大值。
自测 3:IN 和 = 该怎么选?
子查询确定只返回一个值用 =;可能多行就用 IN,否则报 1242。
材料与来源
展开材料出处、讲义页码与证据等级
| 材料 | 类型 / 位置 | 支持了什么 |
|---|---|---|
| BV1Kr4y1i7ru P45(平台标题) | 平台视频页 · P45 | 静帧 t=427s 显示列子查询的 IN 与 > ALL 两段示例;t=488s 为同主题题目 |
| MySQL 8.0 Reference Manual — Subqueries | 官方文档 | 仅用于核对子查询语义与错误码,不是课程材料 |
本集无逐字稿(匿名 player/v2 返回 subtitles=[]、need_login_subtitle=true),依据平台标题、讲义 p82–83「5.6.3 列子查询」与公开静帧核对:讲义操作符表列 IN / NOT IN / ANY / SOME / ALL,并注明 SOME 与 ANY 等同;案例 C 就是「比研发部其中任意一人工资高」。示例表与数据为本笔记自建,不是课程原表。
讲义对照:讲义 5.6.3 列子查询(IN / NOT IN / ANY / SOME / ALL) · p82–83(公开镜像;按主题对应,切点 notexact)
- 画面静帧 9 帧,采样点 0:12–9:58 / 全片 10:11(只用于确认画面主题,不作内容边界)
- 原声字幕未取得:匿名接口字幕轨为空且需登录,未使用任何账号
等级含义:平台视频页 / 官方文档 / 课件 = 原始材料;二手整理 = 参考;推断 = 未经核实。站内补充的解释与练习会在此说明。