case when 必须嵌在 sum 等聚合函数内部,如 sum(case when product_type='自营' then amount else 0 end),漏写 else 0 或未处理 null 会导致结果为 null;不可用 where 过滤替代,也不可将 case 直接用于 group by(除 mysql 8.0+ 外)。

用 CASE WHEN 在 SUM 里做条件求和,别写成多条 SELECT
直接说结论:想按标签分类加总,CASE WHEN 必须嵌在聚合函数内部,不是先 WHERE 再 SUM,也不是写多个 SUM 子查询。常见错误是把分类逻辑放在 GROUP BY 外面,结果要么报错,要么算错总数。
典型场景:销售表里有 product_type 字段,要分别算出「自营」「代销」「联营」三类的销售额总和,但不想查三次或用 UNION。
-
CASE WHEN必须作为SUM的参数,比如SUM(CASE WHEN product_type = '自营' THEN amount ELSE 0 END) -
ELSE 0很关键——漏掉会导致NULL参与运算,整个求和结果变NULL - 别在
CASE外套一层WHERE,那会直接过滤掉其他标签的数据,没法并列统计
CASE WHEN 分组后仍需 GROUP BY?看你要不要拆更细的维度
如果只要一个总行(比如三类销售额并列显示),就不用 GROUP BY;但如果还要按月份、区域等再分组,GROUP BY 就得带上这些字段,且不能只写 CASE 表达式本身(多数数据库不支持表达式直接进 GROUP BY,得重写一遍或用别名)。
- 纯汇总一行:
SELECT SUM(CASE WHEN tag='A' THEN val END) AS a_sum, ... FROM t→ 无GROUP BY - 按
month分组:GROUP BY month,不能写GROUP BY CASE WHEN ...(MySQL 8.0+ 允许,但 PostgreSQL/Oracle 不行) - 想按标签分组显示每类总和?那就别用
CASE做列,直接GROUP BY tag+SUM(val)更干净
空值、类型不一致、条件重叠——三个最常崩的点
CASE WHEN 看似简单,一跑就出数据偏差,往往卡在这三处:
-
NULL值没兜底:比如amount本身是NULL,CASE WHEN tag='A' THEN amount这一句结果还是NULL,SUM会跳过它;稳妥写法是THEN COALESCE(amount, 0) - 分支返回类型不一致:
THEN 100和ELSE 'N/A'混用,某些数据库(如 PostgreSQL)会强制转类型,可能报错或隐式截断 - 条件覆盖不全又没
ELSE:比如只写了WHEN tag IN ('A','B'),但实际还有'C'和NULL,这部分全被当NULL处理,求和就少了一块
性能提醒:别在 CASE 里调子查询或函数
有人为了“灵活”,在 CASE WHEN 里塞 (SELECT name FROM dict WHERE code = t.tag) 或 UPPER(tag),这会让整行计算无法走索引,还可能触发多次执行。尤其在大数据量时,延迟飙升。
- 标签映射类逻辑,提前用
JOIN或物化到主表,别 runtime 查 - 大小写转换这类,如果只是为分类,统一在写入时清洗,查询时直接比对原始值
- 真要动态判断,优先考虑
JOIN+WHERE+GROUP BY组合,比嵌套CASE更易读也更稳
最麻烦的其实是嵌套太深的 CASE:超过三层分支、每个分支还带函数,调试起来连自己都看不懂哪条路径生效了。这种时候,不如拆成视图或 CTE,把分类逻辑单独拎出来。










