cume_dist是sql窗口函数,返回当前行值小于等于它的行数占分区总行数的比例,结果范围为(0,1];它与percent_rank不同,后者基于排名公式计算且首行为0,而cume_dist按实际行数累计、对重复值敏感且天然连续。

什么是 CUME_DIST,它和百分比排位是什么关系
CUME_DIST 返回的是「小于等于当前行值的行数占总行数的比例」,结果范围是 (0, 1],不是从 0 开始,也不是四舍五入后的整数百分比。它天然就是一种累计分布,可以直接当「相对排位百分比」用,但要注意:它不等于「该值在所有唯一值中的位置占比」,而是按行计算,重复值会共享相同结果。
比如 5 行数据中,有 2 行并列第 1,那么这两行的 CUME_DIST 都是 2/5 = 0.4,不是 1/5 或 1/3。
怎么写一个基础的 CUME_DIST 查询
必须配合 ORDER BY 使用,否则语法报错;不能单独在 WHERE 或 SELECT 中裸用。窗口定义里不写 PARTITION BY 就是全表计算。
SELECT score, CUME_DIST() OVER (ORDER BY score) AS cume_pct FROM exam_results;- 如果想看前 3 名的百分比排位,加
LIMIT 3即可,但注意CUME_DIST是在排序后、LIMIT 前计算的,所以结果仍反映全局分布 - 若字段含
NULL,默认排在最前(NULLS FIRST),会影响排位——想把NULL当最小值处理就得显式写ORDER BY score NULLS LAST
和 PERCENT_RANK 混用时容易出什么错
两者都返回 [0,1] 区间值,但算法不同:PERCENT_RANK 是 (rank - 1) / (rows - 1),首行永远是 0;CUME_DIST 是 (≤当前值的行数) / 总行数,首行至少是 1/N。
- 对单值重复多的场景(如大量 60 分),
CUME_DIST会突然跳升(比如从 0.02 直接到 0.35),而PERCENT_RANK更平缓 - 误把
CUME_DIST当成「该分数段的覆盖率」来解释——它不是频次占比,是累计位置占比 - 在分组内计算时,漏写
PARTITION BY导致跨组混算,比如按班级分组却没加PARTITION BY class_id,结果就失去业务意义
性能与兼容性要注意什么
CUME_DIST 是窗口函数,MySQL 8.0.2+ 才稳定支持;低于这个版本会报 FUNCTION does not exist 错误。执行时需全量扫描排序字段,没有对应索引的话,大表(千万级)可能明显变慢。
- 确保
ORDER BY的列上有索引,尤其是用于分组 + 排序的组合(如(class_id, score)) - 不要在子查询或视图里嵌套多层窗口函数,MySQL 8.0 对复杂窗口嵌套优化有限,容易触发临时表或 filesort
- 导出到 Excel 做百分比展示时,记得把
CUME_DIST结果 × 100 并保留两位小数,别直接贴原始浮点值(比如 0.9999999999999999)
真正要小心的是重复值 + 分组边界交叉的场景,比如同一分数横跨两个班级,CUME_DIST 在每个分组内独立计算,但人眼容易误读为全局连续排位。











