# P44 44. 基础-多表查询-标量子查询

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

> 以同版讲义的公开镜像核对章节与页码（镜像非官方出品）；非逐字稿，示例为原创补充。

## P44 44. 基础-多表查询-标量子查询

- 原视频：https://www.bilibili.com/video/BV1Kr4y1i7ru/?p=44（p=44），时长 5:53
- 讲义：5.6.2 标量子查询 p81–82（公开镜像；按主题对应，切点 notexact）

- 本集练习数据：practice/p44.sql（先执行，再对照小例）

### 一句话理解

标量子查询返回一个值（一行一列），所以能直接放在 =、>、< 后面当普通数字用。

### 跟播：视频里 ↔ 本站

视频用「查询工资高于平均工资的员工」演示标量子查询。

| 视频里 / 原课字段 | 本站对应 |
|---|---|
| (select avg(salary) from emp) | (select avg(salary) from employee) |
| emp.salary 是 INT、17 行 | employee.salary 是 INT、4 行 |

看完应能：知道标量子查询只返回一个值，返回多行会报 1242

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

### 步骤

1. 先确认内层只可能返回一行一列。按主键查、或用 AVG/MAX 这类聚合，天然只有一行；按普通字段查就可能翻车。
2. 把内层当成一个字面值来读。WHERE salary > (SELECT AVG(salary) ...) 就是“工资大于 10000”，理解上不需要特殊语法。
3. 跑之前先单独执行内层。看到 0 行或 2 行以上就要预警：0 行时内层得到 NULL，用 `=`、`>`、`<` 这类普通比较会得到 unknown，外层筛不出行；2 行以上直接报 1242。只有 `IS NULL`、`IS NOT NULL` 和 `<=>` 这类专门处理 NULL 的写法是例外——空集会被当成一个 NULL“值”来判，`WHERE (SELECT ...) IS NULL` 反而能查到行。
4. 写复杂条件时，先把内层结果抄成常量试跑外层，两次都对，组合起来基本不会错。

### SQL 示例

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

-- 内层只有一个值：全公司平均工资
SELECT name AS 员工, salary AS 工资
FROM employee
WHERE salary > (SELECT AVG(salary) FROM employee);

-- 内层按 name 查，本数据里恰好一行；name 没有唯一约束，出现重名部门就会返回多行、外层报 1242
SELECT name AS 员工
FROM employee
WHERE dept_id = (SELECT id FROM department WHERE name = '测试部');
```

说明：第一段内层 AVG = 10000，外层只剩小陈 12000，1 行。第二段内层查出测试部 id = 2，外层得到小陈，1 行。如果把“测试部”改成不存在的名字，内层 0 行 → 返回 NULL → 外层一行都没有；这不是语法错，是逻辑上空了（这里用的是 `=`，所以空集筛不出行；换成 `IS NULL` 判断就是例外）。 排查顺序也简单：先单独跑内层看行数，再把值写成常量跑外层，问题一定出在其中一步。要让内层稳定只返回一行，就按主键查，或用 AVG/MAX 这类聚合。

### 易错点

- 内层 0 行不是报错，而是得到 NULL，外层条件静默落空；排查时先单独跑内层。
- 内层返回 2 行以上报 ERROR 1242，常见于按 name 查而 name 没有唯一约束。
- AVG/SUM 跳过 NULL，但 COUNT(*) 不跳过；算平均工资时别把没工资的人当成 0。

### 30 秒速记

标量=一行一列；能当普通值用；0 行→NULL，普通比较筛不出（IS NULL/<=> 例外）；多行→ERROR 1242。

### 自测

1. 标量子查询返回 0 行，外层 WHERE 会怎样？
   - 答：内层为 NULL，比较结果为 unknown，外层不返回该行，也不报错；只有 IS NULL / <=> 这类专门处理 NULL 的写法才会把它当值判。
2. 返回 3 行呢？
   - 答：报 ERROR 1242 Subquery returns more than 1 row。
3. 内层用了 GROUP BY 还能当标量用吗？
   - 答：通常不能，分组多半返回多行；标量位置只接受一行一列，多行报 1242。

### 材料与来源

- [平台视频页] BV1Kr4y1i7ru P44（平台标题） https://www.bilibili.com/video/BV1Kr4y1i7ru/?p=44
- [官方文档] MySQL 8.0 Reference Manual — Subqueries https://dev.mysql.com/doc/refman/8.0/en/subqueries.html

证据说明：本集无逐字稿（匿名 player/v2 返回 subtitles=[]、need_login_subtitle=true），并以讲义公开镜像讲义 5.6.2 标量子查询（p81–82）核对章节与主题；画面静帧只用于确认场景，不是内容边界。示例表与数据为本笔记自建，不是课程原表；不含原始帧或字幕。 本集静帧可读文字很少，仅标题级；不据此声称讲师原话或原例。
