必须同时写group by和聚合函数,否则结果错误:漏group by则行数不变、仅条件投影出null列;不套sum/count等聚合函数,数据库报错或拒绝执行;case when本身非聚合操作,需外层聚合函数压缩行并生成列。

直接用 GROUP BY 配合 CASE WHEN + 聚合函数,就能实现数据透视,不需要额外语法或扩展功能。
为什么必须同时写 GROUP BY 和聚合函数?
漏掉 GROUP BY,结果会变成原始行数 × 列数,每行只填一个分支值,其余全是 NULL;不套 SUM()、COUNT() 这类聚合函数,MySQL 报 Invalid use of group function,PostgreSQL 直接拒绝执行。
-
CASE WHEN product = 'A' THEN amount END本身只是条件筛选,不是聚合操作 - 每个
CASE WHEN分支外层必须包一层聚合函数,比如SUM(CASE WHEN ...) -
GROUP BY字段必须覆盖SELECT中所有未被聚合的列,例如按date分组,就不能再 SELECT 一个没聚合的city
CASE WHEN 分支里要不要写 ELSE?
要写,而且推荐写 ELSE 0,而不是留空或 ELSE NULL。不写 ELSE 时,不匹配的行默认为 NULL,而 SUM() 会跳过 NULL,导致结果偏小;COUNT() 也一样,COUNT(CASE WHEN ...) 不计 NULL,但 COUNT(CASE WHEN ... ELSE 0) 会把 0 当作有效值计入(注意:实际是计数非 NULL 值,所以更稳妥的是用 COUNT(*) FILTER (WHERE ...) 或显式 ELSE 0 配合 SUM)。
- 正确写法:
SUM(CASE WHEN area = 'A区' THEN price ELSE 0 END) - 错误写法:
SUM(CASE WHEN area = 'A区' THEN price END)—— 缺ELSE,结果可能少算 -
COUNT()场景下,COUNT(CASE WHEN ... THEN 1 END)等价于SUM(CASE WHEN ... THEN 1 ELSE 0 END),语义更清晰
动态列名为什么不能在单条 SQL 里自动生成?
SQL 标准不支持运行时推导列名,数据库在解析阶段就需要知道输出字段结构。PIVOT(如 SQL Server)或 TABLE 函数(如 PostgreSQL 的 crosstab())也只是语法糖,背后仍是静态定义列名。
- MySQL 动态拼接得靠
GROUP_CONCAT+PREPARE,但group_concat_max_len默认只有 1024,列一多就截断 - 字符串里单引号必须双写:
CONCAT('SUM(CASE WHEN area = ''', area_name, ''' THEN price ELSE 0 END) AS ', area_name) -
EXECUTE只能在存储过程或函数内用,直接在客户端执行变量 SQL 会报Dynamic SQL is not allowed in this context
真正容易被忽略的点是:CASE WHEN 表达式必须在 SELECT 和 GROUP BY 里完全一致——包括空格、大小写、括号位置。哪怕多一个空格,MySQL 就当成两个不同表达式,导致分组失效或报错。











