3. SQL 基础回顾:SELECT查询、WHERE条件过滤、聚合函数与GROUP BY分组

在实时交易风控巡检中,SQL 是提取、过滤、汇总交易数据的核心工具。本节将系统回顾四个最基础也最关键的 SQL 子句:SELECT、WHERE、聚合函数 与 GROUP BY。掌握这些语法,是后续构建告警阈值与稳定性分析的前提。

3.1 SELECT 查询:数据检索的起点

SELECT 用于指定要从表中检索哪些列。在风控场景中,通常需要从交易流水表(如 transactions)中提取交易 ID、金额、时间、商户号等字段。

基础语法:
SELECT column1, column2, ...
FROM table_name;

若要查询所有列,可使用 SELECT *,但在生产环境中应尽量避免,以减少 I/O 开销。

查询目标 SQL 示例 说明
查询指定列 SELECT trans_id, amount, trans_time FROM transactions; 只返回交易ID、金额、时间三列
查询所有列 SELECT * FROM transactions; 返回所有字段,谨慎使用
使用别名 SELECT amount AS 交易金额 FROM transactions; 用 AS 为列起别名,增强可读性

3.2 WHERE 条件过滤:精准定位风险交易

WHERE 子句用于过滤记录,只返回满足条件的行。在风控巡检中,这是定位异常交易的核心手段。

风控常用过滤条件:
  • 金额阈值:WHERE amount > 10000(大额交易)
  • 时间范围:WHERE trans_time >= '2025-01-01'(指定日期后)
  • 多条件组合:WHERE status = '失败' AND retry_count > 3
  • 范围查询:WHERE amount BETWEEN 5000 AND 20000
  • 集合匹配:WHERE merchant_id IN ('M001', 'M045', 'M102')
-- 示例:查询过去1小时内金额超过5万元且状态为“成功”的交易
SELECT trans_id, amount, trans_time, merchant_id
FROM transactions
WHERE trans_time >= NOW() - INTERVAL '1 hour'
  AND amount > 50000
  AND status = 'success';

3.3 聚合函数:从明细到统计

聚合函数对一组值执行计算并返回单个值。在告警阈值分析中,聚合函数用于计算均值、总和、计数等统计量。

函数 作用 风控应用场景
COUNT(*) 统计行数 统计某时段交易笔数
COUNT(DISTINCT col) 统计不重复值的数量 统计不同商户数、不同IP数
SUM(col) 求和 计算总交易金额
AVG(col) 求平均值 计算平均交易金额
MAX(col) 求最大值 找出单笔最大金额
MIN(col) 求最小值 找出单笔最小金额
注意:聚合函数会忽略 NULL 值(COUNT(*) 除外,它统计所有行)。在计算平均值时,如果某行金额为 NULL,该行不会被计入分母。

3.4 GROUP BY 分组:按维度聚合

GROUP BY 将结果集按一个或多个列分组,然后对每个组应用聚合函数。这是风控巡检中按商户、渠道、时间窗口等维度进行统计的关键操作。

核心规则:
  • SELECT 子句中出现的非聚合列,必须出现在 GROUP BY 中。
  • WHERE 在分组前过滤行,HAVING 在分组后过滤组。
-- 示例:按商户分组,统计每个商户的交易笔数、总金额和平均金额
SELECT merchant_id,
       COUNT(*) AS 交易笔数,
       SUM(amount) AS 总金额,
       AVG(amount) AS 平均金额
FROM transactions
WHERE trans_time >= '2025-06-01'
GROUP BY merchant_id
ORDER BY 总金额 DESC;
SQL 查询执行流程:从原始表到聚合结果 SQL 查询执行流程:从原始表到聚合结果 原始交易表 transactions WHERE 过滤 条件筛选行 GROUP BY 分组 按维度分组 聚合函数 COUNT/SUM/AVG 输出:分组聚合结果集 每个分组一行,包含统计指标

3.5 综合案例:实时风控巡检中的 SQL 组合

以下是一个贴近真实巡检场景的 SQL 示例,综合运用了本节所有知识点:

-- 巡检目标:按商户和小时统计交易量,识别异常激增
SELECT
    merchant_id,
    DATE_TRUNC('hour', trans_time) AS 交易小时,
    COUNT(*) AS 交易笔数,
    SUM(amount) AS 交易总金额,
    AVG(amount) AS 平均金额,
    MAX(amount) AS 最大单笔金额
FROM transactions
WHERE trans_time >= NOW() - INTERVAL '24 hours'
  AND status = 'success'
GROUP BY merchant_id, DATE_TRUNC('hour', trans_time)
HAVING COUNT(*) > 100          -- 笔数超过100的时段
   OR SUM(amount) > 500000     -- 或总金额超过50万
ORDER BY 交易小时 DESC, 交易总金额 DESC;
巡检要点:
  • WHERE 先过滤出过去24小时的成功交易,减少计算量。
  • GROUP BY 按商户和小时两个维度分组,实现细粒度监控。
  • HAVING 在分组后筛选出笔数或金额异常的时段,直接定位风险窗口。
  • ORDER BY 按时间倒序、金额降序排列,优先查看最新且金额最大的异常。
GROUP BY + 聚合函数:明细数据到分组统计 GROUP BY + 聚合函数:明细数据到分组统计 原始明细数据 merchant_id | amount M001 | 1200 M001 | 3500 M002 | 800 M001 | 2100 M002 | 950 M003 | 5000 ... GROUP BY merchant_id 分组1: M001 分组2: M002 分组3: M003 每个组内应用聚合函数 COUNT / SUM / AVG 分组聚合结果 merchant_id | cnt | sum M001 | 3 | 6800 M002 | 2 | 1750 M003 | 1 | 5000 每商户一行统计

3.6 常见错误与避坑指南

错误类型 错误示例 正确写法 说明
SELECT 列未在 GROUP BY 中 SELECT merchant_id, amount, COUNT(*) FROM t GROUP BY merchant_id; SELECT merchant_id, SUM(amount), COUNT(*) FROM t GROUP BY merchant_id; amount 非聚合列且未出现在 GROUP BY 中,多数数据库会报错
WHERE 中使用聚合函数 WHERE COUNT(*) > 10 使用 HAVING COUNT(*) > 10 WHERE 在分组前执行,不能引用聚合结果
COUNT(*) 与 COUNT(col) 混淆 COUNT(amount) 期望统计所有行 明确需求:COUNT(*) 统计行数,COUNT(amount) 统计非 NULL 行数 若 amount 列存在 NULL,两者结果不同
HAVING 与 WHERE 顺序颠倒 GROUP BY ... HAVING ... WHERE ... WHERE ... GROUP BY ... HAVING ... SQL 执行顺序:WHERE → GROUP BY → HAVING
性能提示:在实时风控巡检中,尽量在 WHERE 阶段过滤掉大量无关数据,减少 GROUP BY 的处理行数。对于亿级表,建议先按时间分区,再在 WHERE 中指定时间范围,避免全表扫描。