3. SQL样本基础结构:SELECT语句结构、WHERE条件过滤、JOIN关联规则、GROUP BY聚合逻辑
在实时风控样本校验中,SQL是提取、清洗、关联和聚合数据的核心工具。一个标准的校验SQL样本通常由四大子句构成:SELECT(投影)、WHERE(过滤)、JOIN(关联)和GROUP BY(聚合)。理解每个子句的语义、执行顺序及常见陷阱,是构建高质量校验逻辑的前提。
3.1 SELECT语句结构:投影与表达式
SELECT子句定义输出列,可以是原始字段、计算表达式或聚合函数。在风控场景中,投影列必须明确、无歧义,避免使用SELECT *。
| 投影类型 | 示例 | 风控校验用途 |
|---|---|---|
| 原始字段 | user_id, trans_amount |
直接提取交易主体与金额 |
| 计算表达式 | trans_amount * 0.01 AS fee |
计算手续费、折扣后金额 |
| 聚合函数 | COUNT(*), SUM(amount) |
统计频次、汇总金额 |
| 条件表达式 | CASE WHEN status='FAIL' THEN 1 ELSE 0 END |
标记异常状态 |
校验要点:SELECT中所有非聚合列必须出现在GROUP BY子句中(MySQL宽松模式下除外,但风控校验应严格遵循SQL标准)。别名(AS)应使用有业务含义的英文,避免中文或特殊字符。
3.2 WHERE条件过滤:数据范围裁剪
WHERE子句在数据进入聚合或关联之前,先行过滤掉不满足条件的行。在实时风控中,WHERE条件通常用于限定时间窗口、状态、阈值等。
- 时间窗口过滤:
WHERE trans_time >= NOW() - INTERVAL '1' HOUR—— 只取最近1小时数据。 - 状态过滤:
WHERE status IN ('PENDING', 'PROCESSING')—— 排除已终态记录。 - 阈值过滤:
WHERE trans_amount > 10000—— 只关注大额交易。 - 空值处理:
WHERE risk_score IS NOT NULL—— 剔除无效评分。
常见陷阱:WHERE子句中不能直接使用聚合函数(如
WHERE COUNT(*) > 5是错误的),聚合后的过滤应使用HAVING子句。此外,对索引字段使用函数(如WHERE DATE(trans_time) = '2025-01-01')会导致索引失效,应改为范围查询。
3.3 JOIN关联规则:表连接与数据完整性
风控样本常需关联多张表(交易表、用户表、设备表、黑名单表等)。JOIN类型的选择直接影响结果集的完整性和校验准确性。
| JOIN类型 | 语义 | 风控场景示例 |
|---|---|---|
| INNER JOIN | 仅保留两表匹配的行 | 交易表关联用户表,只取有完整用户信息的交易 |
| LEFT JOIN | 保留左表全部行,右表无匹配时填充NULL | 交易表左关联黑名单表,标记未命中黑名单的交易 |
| RIGHT JOIN | 保留右表全部行,左表无匹配时填充NULL | 较少使用,可用LEFT JOIN改写 |
| FULL OUTER JOIN | 保留两表全部行,无匹配时填充NULL | 对账场景:找出双方不匹配的记录 |
关联键校验:JOIN条件必须使用索引字段(如
ON t.user_id = u.user_id),避免使用ON t.user_name LIKE '%' || u.name || '%'等非等值条件,否则会导致笛卡尔积或性能灾难。实时风控中,建议所有JOIN都使用INNER JOIN或LEFT JOIN,避免RIGHT JOIN和FULL JOIN带来的语义混淆。
3.4 GROUP BY聚合逻辑:分组与汇总
GROUP BY将数据按一个或多个列分组,然后对每组应用聚合函数。在风控样本中,聚合常用于计算频次、总和、均值、最大值、最小值等统计量。
-- 示例:统计每个用户最近1小时内的交易频次与总金额
SELECT
user_id,
COUNT(*) AS trans_count,
SUM(trans_amount) AS total_amount,
MAX(trans_amount) AS max_amount,
AVG(risk_score) AS avg_risk_score
FROM transaction
WHERE trans_time >= NOW() - INTERVAL '1' HOUR
GROUP BY user_id
HAVING COUNT(*) >= 5
ORDER BY total_amount DESC;
聚合校验规则:
- GROUP BY列必须出现在SELECT中(非聚合列),否则结果集语义不明确。
- HAVING用于过滤聚合后的结果,与WHERE分工明确:WHERE过滤行,HAVING过滤组。
- 实时风控中,GROUP BY的维度不宜过多(建议≤3个),否则计算开销大,影响延迟。
- 注意NULL值处理:GROUP BY将NULL视为一个独立分组。
3.5 子句组合校验清单
在实际风控样本校验中,建议按以下清单逐项检查SQL样本的完整性:
| 检查项 | 校验规则 | 错误示例 |
|---|---|---|
| SELECT列完整性 | 非聚合列必须出现在GROUP BY中 | SELECT user_id, COUNT(*) FROM t(缺少GROUP BY) |
| WHERE条件位置 | 过滤行级数据,不能包含聚合函数 | WHERE COUNT(*) > 5(应使用HAVING) |
| JOIN条件明确 | 使用等值关联,避免隐式笛卡尔积 | FROM t1, t2(缺少ON条件) |
| GROUP BY维度 | 维度列数≤3,避免过度分组 | GROUP BY user_id, device_id, ip, hour, minute(粒度过细) |
| HAVING使用 | 聚合后过滤必须用HAVING | WHERE SUM(amount) > 1000(语法错误) |
实时风控最佳实践:在编写校验SQL时,先写FROM+JOIN确定数据源,再写WHERE缩小范围,然后写GROUP BY定义聚合粒度,最后写SELECT投影列。这种“自底向上”的构建方式能有效减少逻辑错误,也便于后续性能调优。