4. CASE WHEN 条件逻辑:标记异常、分类统计与条件计数

CASE WHEN 是 SQL 中实现条件分支的核心语法,在数据质量探查中,它能够帮助我们根据字段值动态生成新标签、对异常数据进行标记、完成复杂的分类汇总,以及实现条件计数。掌握 CASE WHEN,是数据探查从“看数据”走向“判数据”的关键一步。

4.1 语法结构:两种写法

写法 语法 适用场景
简单 CASE CASE 字段 WHEN 值1 THEN 结果1 WHEN 值2 THEN 结果2 ELSE 默认 END 字段值与固定枚举值一一匹配(如性别、状态码)
搜索 CASE CASE WHEN 条件1 THEN 结果1 WHEN 条件2 THEN 结果2 ELSE 默认 END 基于范围、多字段组合、复杂布尔表达式判断(如年龄区间、异常规则)
探查实践建议: 数据质量探查中优先使用搜索 CASE,因为它能灵活处理 NULL、边界值、多条件组合,是标记异常值的主要工具。

4.2 数据探查三大应用场景

4.2.1 标记异常值

通过 CASE WHEN 将不符合业务规则的数据打上“异常”标签,便于后续过滤或统计异常率。

-- 标记订单金额异常:负值或超过 100 万
SELECT
  order_id,
  amount,
  CASE
    WHEN amount IS NULL THEN '空值'
    WHEN amount < 0 THEN '负值异常'
    WHEN amount > 1000000 THEN '超限异常'
    ELSE '正常'
  END AS amount_status
FROM orders;

4.2.2 分类统计

将连续值或离散值映射为业务分类,配合 GROUP BY 实现多维度汇总。

-- 按年龄分组统计用户分布
SELECT
  CASE
    WHEN age < 18 THEN '未成年'
    WHEN age BETWEEN 18 AND 30 THEN '青年'
    WHEN age BETWEEN 31 AND 50 THEN '中年'
    WHEN age > 50 THEN '老年'
    ELSE '未知'
  END AS age_group,
  COUNT(*) AS user_count
FROM users
GROUP BY age_group;

4.2.3 条件计数

在 COUNT 或 SUM 中嵌入 CASE WHEN,实现单行多条件计数,避免多次扫描表。

-- 一次查询统计各类异常数量
SELECT
  COUNT(*) AS total_records,
  SUM(CASE WHEN amount IS NULL THEN 1 ELSE 0 END) AS null_count,
  SUM(CASE WHEN amount < 0 THEN 1 ELSE 0 END) AS negative_count,
  SUM(CASE WHEN amount > 1000000 THEN 1 ELSE 0 END) AS over_limit_count
FROM orders;
效率提示: 条件计数比写多个 COUNT(CASE...) 子查询更高效,尤其在大表探查时,一次扫描即可完成多个质量指标计算。

4.3 CASE WHEN 执行流程

CASE WHEN 执行流程(搜索 CASE) 逐行读取字段值 WHEN 条件1 为 TRUE? 返回 THEN 结果1 WHEN 条件2 为 TRUE? 返回 THEN 结果2 ELSE 默认值 输出结果列
注意: CASE WHEN 按顺序评估条件,一旦某个 WHEN 条件为 TRUE,立即返回对应结果,不再评估后续条件。因此,应将最严格或最具体的条件放在前面。

4.4 常见陷阱与避坑指南

陷阱 错误示例 正确做法
NULL 处理遗漏 CASE WHEN amount > 0 THEN '正数' ELSE '非正' END
(NULL 被归入 ELSE)
先判断 WHEN amount IS NULL THEN '空值'
条件顺序错误 WHEN age > 18 THEN '成年' WHEN age > 60 THEN '老年'
(老年永远不触发)
将最具体条件放前:WHEN age > 60 THEN '老年' WHEN age > 18 THEN '成年'
数据类型不一致 CASE WHEN flag=1 THEN '是' ELSE 0 END
(字符串与数字混用)
所有 THEN/ELSE 返回同一数据类型
忘记 END CASE WHEN ... THEN ... ELSE ... 缺少 END 每个 CASE 必须配对 END

4.5 实战案例:客户数据质量探查

-- 综合探查:标记异常 + 分类统计 + 条件计数
SELECT
  -- 条件计数:各类异常数量
  COUNT(*) AS total_customers,
  SUM(CASE WHEN name IS NULL OR TRIM(name) = '' THEN 1 ELSE 0 END) AS name_issue_count,
  SUM(CASE WHEN phone NOT REGEXP '^1[3-9]\\d{9}$' THEN 1 ELSE 0 END) AS phone_issue_count,
  SUM(CASE WHEN email NOT LIKE '%@%.%' THEN 1 ELSE 0 END) AS email_issue_count,
  -- 分类统计:按数据质量等级分组
  CASE
    WHEN name IS NULL OR phone IS NULL OR email IS NULL THEN '严重缺失'
    WHEN TRIM(name) = '' OR phone NOT REGEXP '^1[3-9]\\d{9}$' THEN '格式异常'
    ELSE '质量合格'
  END AS quality_level,
  COUNT(*) AS level_count
FROM customers
GROUP BY quality_level;
探查要点: 一次查询同时输出总体异常计数和按质量等级的分组统计,既能看到全局异常率,又能定位到具体哪些记录属于哪个等级,是数据质量探查的典型输出模式。