CUME_DIST 是什么
CUME_DIST() 是窗口函数,返回「小于等于当前排序值的行数」占分区总行数的比例,取值区间为 (0,1],常用于分位点、占比分档和成绩分布。它的计算口径建立在整个分区上,属于排名类函数,不要按帧去理解。与 PERCENT_RANK 的区别在于并列值的处理方式与下限位置。
基本信息
| 类型 | 排名类窗口函数,MySQL 8.0、PostgreSQL 等主流实现都支持 |
|---|---|
| 计算口径 | 小于等于当前值的行数 ÷ 分区总行数 |
| 取值范围 | 大于 0、小于等于 1 |
| 方向影响 | 升序表示不超过当前值,降序表示不低于当前值 |
| 并列处理 | 并列行得到完全相同的累积占比 |
两种分布函数对照
| 对比项 | CUME_DIST | PERCENT_RANK |
|---|---|---|
| 公式 | 小于等于当前值的行数 ÷ 总行数 | (名次 − 1) ÷ (总行数 − 1) |
| 下限 | 无并列时为 1 ÷ 总行数 | 第一行为 0 |
| 上限 | 1 | 1 |
| 并列值 | 并列行完全相同 | 并列行相同,但数值与前者不同 |
| 典型用途 | 算分位点、看多少行不超过它 | 看相对名次位置 |
典型使用场景
- 成绩分档:算出每个分数所处的位置,直接切前后各多少比例
- 阈值定位:求累积占比刚好越过某比例的分数,作为分数线
- 分组分布对比:按城市或渠道分区,比较组内部分布的陡缓
- 异常值观察:看处于分布尾部若干比例的行有哪些
- 与排名函数互为验证:同一批数据用两种口径交叉核对
- 能力评分:把多个指标转成组内占比后再加权合成
计算与取分位点
计算与取分位点
SELECT name, score,
ROUND(CUME_DIST() OVER (ORDER BY score), 4) AS cume, # 不超过该分数的行占比
ROUND(PERCENT_RANK() OVER (ORDER BY score), 4) AS prank # 相对名次
FROM exams;
SELECT score, CUME_DIST() OVER (ORDER BY score DESC) AS cd # 降序后含义变为「不低于」
FROM exams;
SELECT MIN(score) FROM ( # 取近似九十分位点
SELECT score, CUME_DIST() OVER (ORDER BY score) AS cd FROM exams
) t WHERE cd >= 0.9;
SELECT city, score, CUME_DIST() OVER (PARTITION BY city ORDER BY score) AS cd
FROM exams; # 每个分组各自计算分布升序与降序直接决定这句话的意思:升序时表示「小于等于当前值的行占比」,降序时表示「大于等于当前值的行占比」。对外报数或画图之前,把方向写进口径说明,否则同一列数字会被两种理解同时使用。
如果需要「截至当前行的累计占比」(例如累计销售额占总量比例),那是另一种算法:用 SUM() 开窗配合 SUM() OVER () 求总量自行相除,不要套用 CUME_DIST,它的口径是行数而不是指标值。
两点要留神:一是小样本上分布值跳动很大,十几行数据里相邻两行可能差好几个百分点,拿它当分档阈值不稳;二是含空值时排序位置由实现决定,空值参与后累积占比会整体偏移,对分布敏感的指标应先过滤空值或在排序里控制空值位置。