本章要回答的三个问题:SELECT 的列位置上除了列名还能放什么?为什么 NULL 会让 WHERE 的判断"三个值"来回跳,又该怎么稳稳地筛出它?怎么在查询里实现"按条件分支",让一列数据变成标签、档位和口径?回答完这三个问题,你的单表查询就从"取数"进化到"加工"。
第 1 章的查询只能"原样取数":列里存什么就查什么。但真实需求几乎从不这么客气——报表要"库存金额 = 价格 × 库存",运营要"价格带"这种表里根本没有的列,数据清洗要处理大量没填的字段。这些活儿不该倒在应用层用 Python 逐行处理:数据在数据库里加工一次,比搬运百万行到应用端再加工快得多,也让口径统一在同一个地方。
本章的两个主角各有脾气。NULL 不是值,是"未知"的占位,它让等号失灵、让聚合函数悄悄跳过它、让 NOT IN 整体翻车——第 6 章的子查询陷阱、第 4 章的 COUNT 差异,根子都在这里。CASE 表达式则是 SQL 里唯一的分支结构,第 7 章窗口函数的很多经典写法,本质都是"窗口函数 + CASE"的组合拳。把这两个地基砖烧结实,后面的楼层才敢往上盖。
| 节 | 回答哪个问题 | 关键产出 |
|---|---|---|
| 3.1 表达式、函数与 NULL | 列上能做什么、NULL 怎么回事 | 表达式与函数地图、三值逻辑与空值处理 |
| 3.2 CASE 表达式 | 分支怎么写 | 搜索式与简单式 CASE、打标分档与聚合中的 CASE |
单表表达力是查询的"内功”:同样一份数据,别人搬出去加工,你在库内一步到位——快,而且口径只有一份。
现在你能在单行层面加工数据了。下一章把视角从"行"抬到"组":聚合函数把多行折叠成一个数,GROUP BY 决定按什么折叠,HAVING 在折叠之后继续筛选。折叠是 SQL 思维的第一次跃迁,也埋下"明细行被吃掉"的遗憾——那个遗憾会由第 7 章的窗口函数来偿。