3. SQL基础回顾:SELECT、WHERE、JOIN、GROUP BY、HAVING、ORDER BY等核心语法

在信用评分模型A/B测试中,SQL是数据提取、特征加工与效果评估的核心工具。无论是计算坏账率、对比实验组与对照组,还是生成PSM匹配样本,都离不开SQL的精准操作。本节将系统回顾SQL最常用的六大核心语法,并结合信用评分场景给出实战示例。

3.1 SELECT & FROM:数据检索基础

SELECT 用于指定要查询的字段,FROM 指定数据来源表。在信用评分项目中,通常从用户主表、交易流水表、逾期标签表中提取数据。

信用评分场景示例: 提取申请用户的基础信息与最终逾期标签。
-- 提取申请用户ID、年龄、收入等级与最终逾期标签
SELECT 
    user_id,
    age,
    income_level,
    is_default_90dpd
FROM credit_application
WHERE application_date BETWEEN '2024-01-01' AND '2024-06-30';
关键字 作用 信用评分常见用法
SELECT 指定返回的列 选择特征字段、标签字段、分组统计值
FROM 指定数据表 关联用户表、交易表、催收表
AS 设置别名 简化长表名或字段名,提高可读性

3.2 WHERE:条件过滤

WHERE 用于在数据提取阶段过滤行记录。在A/B测试中,常用来筛选实验组、对照组或特定时间窗口的数据。

避坑提示: 在信用评分模型中,WHERE 条件中避免使用函数包裹索引字段(如 WHERE DATE(apply_time) = '2024-01-01'),会导致索引失效,应使用范围查询 WHERE apply_time >= '2024-01-01' AND apply_time < '2024-01-02'。
-- 筛选A/B测试中的实验组用户(策略A)
SELECT 
    user_id,
    credit_score,
    loan_amount
FROM credit_application
WHERE experiment_group = 'treatment_A'
  AND application_date >= '2024-03-01'
  AND loan_amount BETWEEN 5000 AND 50000;

3.3 JOIN:多表关联

信用评分建模通常需要将用户基本信息、交易行为、历史逾期记录合并到一张宽表中。JOIN 是实现多表关联的核心操作。

信用评分多表JOIN关联示意图 用户主表 user_id age, gender income_level 交易流水表 user_id trans_amount trans_date 逾期标签表 user_id is_default overdue_days 建模宽表(JOIN结果) user_id + age + income + trans_amount + is_default
-- 将用户主表与交易流水表、逾期标签表关联
SELECT 
    a.user_id,
    a.age,
    a.income_level,
    b.total_trans_amount,
    c.is_default_90dpd
FROM credit_user a
LEFT JOIN (
    SELECT user_id, SUM(trans_amount) AS total_trans_amount
    FROM transaction_record
    WHERE trans_date >= '2024-01-01'
    GROUP BY user_id
) b ON a.user_id = b.user_id
LEFT JOIN default_label c ON a.user_id = c.user_id
WHERE a.application_date >= '2024-01-01';
JOIN类型 返回结果 信用评分使用场景
INNER JOIN 仅返回匹配成功的记录 只分析有完整交易记录的用户
LEFT JOIN 保留左表全部记录,右表无匹配则填NULL 保留所有申请用户,交易数据缺失不影响主表
RIGHT JOIN 保留右表全部记录 较少使用,可用LEFT JOIN改写
FULL OUTER JOIN 保留两表全部记录 数据对账、全量用户画像合并

3.4 GROUP BY & HAVING:分组聚合与过滤

GROUP BY 按指定字段分组,配合聚合函数(COUNT、SUM、AVG、MAX、MIN)计算每组的统计值。HAVING 用于对聚合后的结果进行过滤,与 WHERE 的区别在于 HAVING 作用于分组后。

常见错误: 在 GROUP BY 查询中,SELECT 子句只能包含分组字段和聚合函数。例如 SELECT user_id, age, AVG(loan_amount) 如果 user_id 不是分组字段且 age 未聚合,会报错或返回随机值。
-- 按收入等级分组,计算各组的平均信用分与坏账率
SELECT 
    income_level,
    COUNT(*) AS user_count,
    AVG(credit_score) AS avg_credit_score,
    SUM(CASE WHEN is_default = 1 THEN 1 ELSE 0 END) * 1.0 / COUNT(*) AS bad_rate
FROM credit_user
WHERE application_date >= '2024-01-01'
GROUP BY income_level
HAVING COUNT(*) >= 100  -- 只保留样本量足够的组
ORDER BY bad_rate DESC;
子句 执行顺序 过滤时机 能否使用聚合函数
WHERE 第2步(FROM之后) 分组之前 不能
HAVING 第5步(GROUP BY之后) 分组之后 可以

3.5 ORDER BY:排序输出

ORDER BY 对最终结果集按指定字段排序,ASC 升序(默认),DESC 降序。在信用评分A/B测试中,常用于输出风险最高的用户列表或按实验组排序对比。

-- 输出信用分最低的100个用户,用于人工审核
SELECT 
    user_id,
    credit_score,
    income_level,
    is_default
FROM credit_user
WHERE application_date >= '2024-01-01'
ORDER BY credit_score ASC, is_default DESC
LIMIT 100;

3.6 核心语法执行顺序

理解SQL各子句的逻辑执行顺序,对写出高效、正确的查询至关重要。以下是SQL查询的完整执行顺序:

SQL查询子句逻辑执行顺序 ① FROM / JOIN ② WHERE ③ GROUP BY ④ HAVING ⑤ SELECT ⑥ ORDER BY
实战要点: 由于 WHERE 在 GROUP BY 之前执行,应尽量在 WHERE 中过滤掉无关数据,减少分组计算的数据量,提升查询性能。在信用评分大数据场景下,这一优化可节省数分钟的计算时间。

3.7 信用评分A/B测试综合查询示例

将上述语法综合运用,完成一个典型的A/B测试效果评估查询:对比实验组(新评分模型)与对照组(旧评分模型)在相同时间窗口内的逾期率差异。

-- A/B测试效果评估:实验组 vs 对照组逾期率对比
SELECT 
    experiment_group,
    COUNT(*) AS total_users,
    SUM(is_default_90dpd) AS default_count,
    ROUND(SUM(is_default_90dpd) * 100.0 / COUNT(*), 2) AS bad_rate_pct,
    AVG(credit_score) AS avg_score,
    AVG(loan_amount) AS avg_loan
FROM credit_ab_test
WHERE test_date BETWEEN '2024-04-01' AND '2024-06-30'
  AND experiment_group IN ('treatment', 'control')
GROUP BY experiment_group
HAVING COUNT(*) >= 500
ORDER BY bad_rate_pct ASC;
输出结果解读: 若实验组(treatment)的 bad_rate_pct 显著低于对照组(control),且样本量足够大,则说明新评分模型在风险区分能力上优于旧模型,可考虑全量上线。