4. 窗口函数入门:ROW_NUMBER、RANK、DENSE_RANK 的基本语法与区别

在授信决策引擎中,经常需要对客户按风险评分排序后取前 N 名、计算排名区间或标记批次内偏移位置。传统聚合函数无法保留原始行细节,而窗口函数(Window Function)可以在不改变行数的情况下完成分组排序与编号。本节聚焦三个最常用的排序窗口函数:ROW_NUMBER、RANK 与 DENSE_RANK。

4.1 窗口函数基础语法

所有窗口函数都使用 OVER() 子句定义窗口范围。基本语法结构如下:

<窗口函数>() OVER (
    [PARTITION BY <分组列>]
    ORDER BY <排序列> [ASC | DESC]
)
子句 作用 授信场景示例
PARTITION BY 按指定列分组,函数在每个分组内独立计算 按产品类型分组,分别对客户评分排序
ORDER BY 指定排序字段与方向,决定编号顺序 按风险评分降序排列,评分越高排名越前
ROWS/RANGE (可选)定义窗口帧边界,排序函数通常省略 —
💡 提示: 在授信批次偏移定位中,PARTITION BY 常用于按“机构”、“产品线”或“渠道”分组,确保排名只在同组内比较,避免跨组干扰。

4.2 三个函数的核心区别

ROW_NUMBER、RANK、DENSE_RANK 都用于生成行号或排名,但处理并列值(tie)的方式截然不同。以下表为例,假设有 6 位客户按信用评分降序排列:

客户ID 信用评分 ROW_NUMBER RANK DENSE_RANK
C001 95 1 1 1
C002 92 2 2 2
C003 92 3 2 2
C004 88 4 4 3
C005 85 5 5 4
C006 85 6 5 4
  • ROW_NUMBER:为每一行分配唯一连续整数,即使评分相同也强制区分(通常按物理顺序或 ORDER BY 中额外字段决定先后)。
  • RANK:并列值获得相同排名,但会跳过后续排名号(如并列第 2 名后,下一名是第 4 名)。
  • DENSE_RANK:并列值获得相同排名,且不跳过排名号(如并列第 2 名后,下一名是第 3 名)。
📌 授信决策要点: 若需要为每个客户生成唯一偏移序号(如批次内第几笔),使用 ROW_NUMBER;若需要展示“名次”且允许并列空缺(如竞赛排名),使用 RANK;若需要紧凑排名(如分档、评级),使用 DENSE_RANK。

4.3 排名差异可视化

下图直观展示三个函数在并列值出现时的编号行为差异:

ROW_NUMBER vs RANK vs DENSE_RANK 并列值处理对比 评分 95 92 88 85 ROW_NUMBER 1 1 2 3 4 5 6 RANK 1 2 2 4 5 5 DENSE_RANK 1 2 2 3 4 4

4.4 授信场景实战 SQL

以下 SQL 展示在授信申请表中,按产品类型分组,对客户信用评分降序排名:

SELECT
    apply_id,
    product_type,
    credit_score,
    ROW_NUMBER() OVER (
        PARTITION BY product_type
        ORDER BY credit_score DESC, apply_id ASC
    ) AS row_num,
    RANK() OVER (
        PARTITION BY product_type
        ORDER BY credit_score DESC
    ) AS rank_val,
    DENSE_RANK() OVER (
        PARTITION BY product_type
        ORDER BY credit_score DESC
    ) AS dense_rank_val
FROM credit_apply
WHERE apply_date >= '2025-01-01';
⚠️ 常见陷阱: 使用 ROW_NUMBER 时,若 ORDER BY 字段存在重复值且未指定第二排序字段,每次执行可能得到不同的行号顺序,导致批次偏移定位不稳定。建议始终在 ORDER BY 中追加唯一标识列(如 apply_id)作为 tie-breaker。

4.5 选择指南

业务需求 推荐函数 原因
批次内唯一偏移序号(第 1 笔、第 2 笔…) ROW_NUMBER 每行唯一编号,无并列
客户风险排名展示(允许空缺) RANK 并列名次后跳过,符合传统排名认知
客户分档(A/B/C 级,每档连续) DENSE_RANK 紧凑编号,不产生空档,便于分箱
取每组前 N 名(Top-N 查询) ROW_NUMBER 精确控制返回行数,避免并列导致多出
📌 批次偏移定位应用: 在授信决策引擎中,ROW_NUMBER 常用于生成“批次内偏移序号”,配合 PARTITION BY batch_id 实现每笔申请在所属批次中的精确位置,为后续偏移量计算和窗口聚合提供基础。