4. SQL 基础回顾:SELECT、WHERE、JOIN、GROUP BY、HAVING、ORDER BY 在质量探查中的应用

在风控数据质量治理中,SQL 是探查数据质量最直接、最强大的工具。本章将系统回顾六大核心 SQL 子句——SELECT、WHERE、JOIN、GROUP BY、HAVING、ORDER BY,并逐一演示它们在数据质量探查(Profiling)中的典型应用场景。掌握这些基础,是后续构建自动化质量监控报表的基石。

4.1 六大子句与质量探查的对应关系

每个 SQL 子句在数据质量探查中都有其独特的定位。下表总结了它们各自解决的质量问题类型:

SQL 子句 核心作用 质量探查场景
SELECT 选择列、计算表达式、去重 探查字段空值率、唯一值计数、字段值分布
WHERE 过滤行记录 筛选异常记录、空值记录、超出业务阈值的脏数据
JOIN 关联多张表 探查跨表引用完整性、外键缺失、数据一致性
GROUP BY 按维度分组聚合 统计各分组的记录数、重复度、字段完整性
HAVING 对聚合结果进行过滤 定位重复记录组、低质量分组、异常聚合值
ORDER BY 对结果集排序 按质量指标排序,快速定位最差或最优的数据分区

4.2 SELECT:探查字段级质量

SELECT 是质量探查的起点。通过组合 COUNT、DISTINCT、SUM 等聚合函数,可以快速评估单个字段的健康状况。

🔍 典型探查场景: 计算字段空值率、唯一值比例、值域范围。
-- 探查 loan_amount 字段的空值率与唯一值计数
SELECT
    COUNT(*) AS total_records,
    COUNT(loan_amount) AS non_null_count,
    COUNT(*) - COUNT(loan_amount) AS null_count,
    ROUND(100.0 * (COUNT(*) - COUNT(loan_amount)) / COUNT(*), 2) AS null_rate_pct,
    COUNT(DISTINCT loan_amount) AS unique_values
FROM loan_apply;

4.3 WHERE:精准定位脏数据

WHERE 子句用于从海量数据中快速筛选出不符合质量规则的记录,是数据清洗的前置步骤。

⚠️ 避坑提示: 在 WHERE 条件中对索引字段使用函数(如 WHERE DATE(create_time) = '2024-01-01')会导致索引失效,影响探查性能。建议使用范围查询替代。
-- 筛选出风控业务中典型的脏数据
SELECT
    apply_id,
    id_card,
    phone,
    loan_amount,
    apply_time
FROM loan_apply
WHERE
    -- 身份证号长度不符合18位
    LENGTH(id_card) <> 18
    -- 手机号非11位数字
    OR phone NOT REGEXP '^1[0-9]{10}$'
    -- 贷款金额为负数或超过业务上限
    OR loan_amount <= 0
    OR loan_amount > 1000000
    -- 申请时间在未来
    OR apply_time > NOW();

4.4 JOIN:探查跨表引用完整性

风控数据通常分布在多张表中(如用户表、申请单表、黑名单表)。JOIN 操作可以探查外键缺失、孤儿记录等引用完整性问题。

💡 最佳实践: 使用 LEFT JOIN ... IS NULL 模式来查找在父表中不存在的子表记录,这是探查引用完整性缺失的标准方法。
-- 探查 loan_apply 表中的 user_id 在 user_info 表中是否存在
SELECT
    la.apply_id,
    la.user_id,
    la.loan_amount
FROM loan_apply la
LEFT JOIN user_info ui ON la.user_id = ui.user_id
WHERE ui.user_id IS NULL;  -- 孤儿记录:申请单关联的用户不存在
LEFT JOIN … IS NULL 探查引用完整性 loan_apply(子表) apply_id (PK) user_id (FK) loan_amount apply_time → 包含 user_id=999 user_info(父表) user_id (PK) name phone id_card → 不存在 user_id=999 LEFT JOIN 结果:返回 user_id=999 的孤儿记录

4.5 GROUP BY + HAVING:探查重复与异常分组

GROUP BY 按维度汇总数据,HAVING 则对聚合结果进行二次过滤。两者结合是探查重复记录、异常分组的黄金组合。

🔍 典型探查场景: 查找同一身份证号下存在多个不同手机号的记录(一人多号异常),或同一申请单被重复提交。
-- 探查身份证号下关联多个手机号的异常情况
SELECT
    id_card,
    COUNT(DISTINCT phone) AS phone_count,
    COUNT(*) AS apply_count,
    MIN(apply_time) AS first_apply,
    MAX(apply_time) AS last_apply
FROM loan_apply
WHERE id_card IS NOT NULL
GROUP BY id_card
HAVING COUNT(DISTINCT phone) > 2  -- 同一身份证关联超过2个手机号
   OR COUNT(*) > 5;               -- 同一身份证申请次数超过5次

4.6 ORDER BY:按质量指标排序

ORDER BY 用于对探查结果进行排序,帮助数据治理人员快速聚焦质量最差的区域。通常与 LIMIT 配合使用。

-- 按空值率降序排列,找出质量最差的字段
SELECT
    column_name,
    null_count,
    total_count,
    ROUND(100.0 * null_count / total_count, 2) AS null_rate
FROM (
    SELECT 'id_card' AS column_name, COUNT(*) - COUNT(id_card) AS null_count, COUNT(*) AS total_count FROM loan_apply
    UNION ALL
    SELECT 'phone', COUNT(*) - COUNT(phone), COUNT(*) FROM loan_apply
    UNION ALL
    SELECT 'loan_amount', COUNT(*) - COUNT(loan_amount), COUNT(*) FROM loan_apply
) stats
ORDER BY null_rate DESC;  -- 最差的排在最前面
SQL 六大子句在数据质量探查中的流程 原始数据表 ① SELECT + WHERE:字段探查 & 脏数据筛选 ② JOIN:跨表引用完整性探查 ③ GROUP BY + HAVING:重复 & 异常分组定位 ④ ORDER BY:按质量指标排序,输出质量报告

4.7 综合实战:一次完整的数据质量探查

将六大子句组合使用,可以构建一个端到端的数据质量探查脚本。以下示例综合了字段完整性、引用完整性、重复性三个维度的检查:

-- 综合质量探查:风控申请数据质量报告
WITH
-- 1. 字段完整性探查
field_stats AS (
    SELECT
        COUNT(*) AS total,
        COUNT(id_card) AS id_card_non_null,
        COUNT(phone) AS phone_non_null,
        COUNT(loan_amount) AS amount_non_null
    FROM loan_apply
),
-- 2. 引用完整性探查
ref_integrity AS (
    SELECT COUNT(*) AS orphan_records
    FROM loan_apply la
    LEFT JOIN user_info ui ON la.user_id = ui.user_id
    WHERE ui.user_id IS NULL
),
-- 3. 重复性探查
dup_stats AS (
    SELECT id_card, COUNT(*) AS cnt
    FROM loan_apply
    WHERE id_card IS NOT NULL
    GROUP BY id_card
    HAVING COUNT(*) > 1
)
SELECT
    '字段完整性' AS check_type,
    ROUND(100.0 * (total - id_card_non_null) / total, 2) AS id_card_null_rate,
    ROUND(100.0 * (total - phone_non_null) / total, 2) AS phone_null_rate,
    ROUND(100.0 * (total - amount_non_null) / total, 2) AS amount_null_rate
FROM field_stats
UNION ALL
SELECT '引用完整性', orphan_records, 0, 0 FROM ref_integrity
UNION ALL
SELECT '重复记录数', COUNT(*), 0, 0 FROM dup_stats
ORDER BY check_type;
💡 实战要点:
  • 使用 CTE(WITH 子句)将探查逻辑模块化,便于后续扩展和维护。
  • 空值率、引用缺失率、重复率是风控数据质量的三项核心 KPI。
  • 探查结果应定期落库,形成质量趋势数据,为报表可视化提供数据源。