3. SQL 聚合查询基础回顾:GROUP BY、HAVING、聚合函数在批次场景下的行为
在授信决策引擎的批次偏移分析中,SQL 聚合查询是定位数据差异的核心工具。批次偏移的本质是“同一业务逻辑在不同时间窗口或不同批次间,聚合结果不一致”。因此,深入理解 GROUP BY、HAVING 以及 SUM、COUNT、AVG 等聚合函数在批次数据下的执行行为,是诊断偏移问题的第一步。
3.1 聚合函数在批次场景下的行为差异
聚合函数对一组行执行计算并返回单个值。在批次偏移场景中,最常出现的问题源于聚合函数对 NULL 值、重复记录 以及 边界时间戳 的处理差异。
| 聚合函数 | 批次场景常见陷阱 | 偏移影响 |
|---|---|---|
SUM(column) |
忽略 NULL;若批次内存在重复主键,金额被重复加总 | 授信额度虚高或虚低 |
COUNT(*) vs COUNT(column) |
COUNT(*) 包含 NULL 行;COUNT(column) 跳过 NULL |
批次记录数统计偏差 |
AVG(column) |
受极端值影响大;批次间数据分布变化导致均值漂移 | 评分卡阈值失效 |
MAX/MIN(column) |
批次边界时间戳截断导致极值丢失 | 逾期天数计算错误 |
批次偏移案例: 某风控系统在 T 日跑批时使用
COUNT(apply_id) 统计进件量,但部分 apply_id 为 NULL 的测试记录未被计入,导致与业务报表偏差 2.3%。修正为 COUNT(*) 后对齐。
3.2 GROUP BY 的分组逻辑与批次偏移
GROUP BY 将查询结果按一列或多列分组,然后对每个组应用聚合函数。在批次偏移定位中,GROUP BY 的 分组键选择 直接决定偏移能否被暴露。
- 按批次标识分组: 使用
batch_id或run_date作为分组键,对比不同批次的聚合结果。 - 按业务维度分组: 如
product_type、channel,发现某个维度的偏移被全局聚合掩盖。 - 多列分组顺序: 在批次偏移对比中,
GROUP BY batch_id, product_type与GROUP BY product_type, batch_id结果相同,但执行计划可能不同。
-- 批次偏移对比查询:按批次和产品类型聚合
SELECT
batch_id,
product_type,
COUNT(*) AS apply_cnt,
SUM(loan_amount) AS total_loan,
AVG(risk_score) AS avg_risk
FROM decision_engine.credit_apply
WHERE run_date BETWEEN '2025-01-01' AND '2025-01-31'
GROUP BY batch_id, product_type
ORDER BY batch_id, product_type;
偏移定位技巧: 当怀疑批次偏移时,先使用
GROUP BY batch_id 做粗粒度对比,若发现差异,再逐层下钻到 GROUP BY batch_id, channel, product_type 等细粒度分组,定位偏移源头。
3.3 HAVING 在批次过滤中的特殊作用
HAVING 用于过滤分组后的聚合结果,与 WHERE 在分组前过滤不同。在批次偏移分析中,HAVING 常用于筛选出“异常批次”。
| 过滤阶段 | 关键字 | 批次偏移场景示例 |
|---|---|---|
| 分组前 | WHERE |
过滤掉测试批次、无效记录 |
| 分组后 | HAVING |
筛选出聚合结果偏离阈值的批次 |
-- 使用 HAVING 定位偏移批次:找出平均风险分偏离超过 10% 的批次
SELECT
batch_id,
COUNT(*) AS record_cnt,
AVG(risk_score) AS avg_risk,
STDDEV(risk_score) AS std_risk
FROM decision_engine.credit_apply
WHERE run_date >= '2025-01-01'
GROUP BY batch_id
HAVING ABS(AVG(risk_score) - 650) > 65 -- 假设基准均值为 650
OR COUNT(*) < 1000; -- 批次记录数异常少
性能警告:
HAVING 在分组完成后执行过滤,无法利用索引。对于大表批次对比,建议先用 WHERE 缩小数据范围,再用 HAVING 做聚合后过滤,避免全表分组带来的性能开销。
3.4 聚合查询在批次偏移中的执行流程
理解 SQL 聚合查询的执行顺序,有助于在批次偏移分析中快速定位是“数据问题”还是“查询逻辑问题”。
- FROM + JOIN: 确定数据源,关联多表(如申请主表 + 拒绝原因表)。
- WHERE: 过滤非目标批次、无效数据。
- GROUP BY: 按分组键将数据划分为多个逻辑桶。
- 聚合函数计算: 在每个桶内执行 SUM/COUNT/AVG。
- HAVING: 过滤掉不符合条件的聚合结果。
- SELECT + ORDER BY: 输出最终结果并排序。
3.5 批次偏移聚合查询的常见反模式
在授信决策引擎的批次偏移排查中,以下三种聚合查询反模式最容易导致误判:
| 反模式 | 错误写法示例 | 偏移后果 | 正确做法 |
|---|---|---|---|
| 忽略 NULL 的 COUNT | COUNT(risk_score) |
漏计 NULL 风险分记录,批次统计量偏小 | COUNT(*) 或 COALESCE(risk_score,0) |
| GROUP BY 键不唯一 | GROUP BY batch_id 但同一 batch_id 内主键重复 |
聚合结果被重复记录放大 | 先 DISTINCT 去重或使用窗口函数 |
| HAVING 与 WHERE 混用 | 用 WHERE AVG(score) > 600 |
语法错误或逻辑错误 | 聚合后过滤必须用 HAVING |
实战建议: 在编写批次偏移对比查询时,始终先执行
SELECT batch_id, COUNT(*) AS cnt FROM ... GROUP BY batch_id 确认各批次记录数是否合理,再逐步加入金额、评分等聚合字段。这个“记录数先行”的习惯能快速排除大部分数据源问题。