MySQL 视频课 · 50 集 / 子查询:标量、列、行、表子查询 / P45

第 45 集 / 共 50 · 子查询:标量、列、行、表子查询 · 视频 p=45 · 时长 10:11

P45 45. 基础-多表查询-列子查询

讲义 5.6.3 列子查询(IN / NOT IN / ANY / SOME / ALL) p82–83

按主题对应,非逐句切分

来源与核对说明

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

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

讲义索引:p82–83 · 5.6.3 列子查询(IN / NOT IN / ANY / SOME / ALL) · 切点 notexact

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

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

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

列子查询返回一列多行,等于给你一个集合。既然是一堆值,就不能再用 = 硬接。

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

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

一句话理解

列子查询返回一列多行,等于给你一个集合:在集合里挑值用 IN,拿一个值和整个集合逐个比用 ANY / ALL。

跟播:视频里 ↔ 本站

视频里 / 原课字段本站对应
emp.salary / emp.dept_id(17 行)employee.salary / employee.dept_id(4 行)
研发部 = dept_id 1(讲义 dept 6 行)研发部 = dept_id 1(本站 department 3 行)

看视频时以讲义表为准,跟练时用本站表;结构相同、数字不同。

按这 4 步做

  1. 先确认内层只查一列。多查一列就变成表子查询,IN 接不住;一列多行意味着结果可能是 0 行、1 行或很多行。
  2. IN 判断「在不在这个集合里」,最常用;NOT IN 是它的反面,但集合里有 NULL 时整体变成 unknown,结果常常是 0 行。
  3. ANY(与 SOME 完全同义)是「至少有一个满足」:研发部工资是 8000、10000,salary > ANY(那个子查询)只要大于 8000 就成立,也就是大于集合里的最小值。
  4. ALL 是「全部都满足」:同一份数据里 salary > ALL(那个子查询)要大于 10000,也就是大于集合里的最大值。写完用行数反推,别只看语法。

小例

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

SQL 示例
-- 表: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 的好处是「比其中任意一个高」这种需求能直说。

下面每条只演示一个点,可以单独复制执行。

最小数列:3 个值讲清 ANY 与 ALL
-- 集合 {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)。

补充 SQL
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;

易错点

30 秒速记

列子查询=一列多行;IN 在集合内;NOT IN 遇 NULL 全废;> ALL 等于大于最大值,> ANY 等于大于最小值;SOME 与 ANY 同义。

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

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

下载本集 Markdown