CUME_DIST()是SQL窗口函数,返回当前行值小于等于其在分区内的累积分布比例,结果范围为(0,1],必须配合ORDER BY使用,支持PARTITION BY分组计算,对重复值返回相同值。

什么是 CUME_DIST,它返回什么值
CUME_DIST() 是 SQL 标准中的窗口函数,用来计算当前行在分区内的“累积分布比例”——即值小于等于当前行的行数占分区总行数的比例。结果范围是 (0, 1],最小值一定大于 0(因为至少包含自己),最大值一定是 1(最后一行或并列最大值的所有行都得 1)。
注意它和 PERCENT_RANK() 不同:后者按排名归一化(空缺排名),而 CUME_DIST() 按实际行数计数,对重复值更“宽容”。
常见错误现象:CUME_DIST() OVER () 忘记写 ORDER BY —— 这会导致语法错误(几乎所有数据库都强制要求),因为没有排序就无法定义“小于等于当前行”的集合。
基本用法:必须带 ORDER BY 的窗口定义
CUME_DIST() 只能作为窗口函数使用,且 OVER 子句中 ORDER BY 是必需的,PARTITION BY 是可选的。
典型场景:查每个销售额对应的累计占比,看多少比例的订单金额 ≤ 当前订单。
SELECT order_id, amount, CUME_DIST() OVER (ORDER BY amount) AS cume_dist FROM orders;
- 如果
amount有重复(比如两个订单都是 200),它们会得到相同的CUME_DIST()值(因为“≤200”的行数相同) - 不写
PARTITION BY就是全表作为一个分区;加了之后才按组分别计算 - PostgreSQL、SQL Server、Oracle、Snowflake、BigQuery 都支持;MySQL 8.0+ 支持;SQLite 不支持
和 PARTITION BY 一起用:分组内独立计算累积分布
当需要“每个部门内薪资的累积分布”或“每季度销量的相对位置”时,必须用 PARTITION BY 划分逻辑组。
SELECT
dept,
salary,
CUME_DIST() OVER (PARTITION BY dept ORDER BY salary) AS dist_in_dept
FROM employees;
关键点:
-
PARTITION BY dept表示每个部门单独排序、单独计数,互不影响 - 同一部门里,最低薪员工的
CUME_DIST()= 1 / 该部门人数;最高薪一定是 1 - 跨部门不能直接比较
dist_in_dept值——A 部门的 0.6 和 B 部门的 0.6 含义不同(分母不同) - 若某部门只有 1 人,其
CUME_DIST()一定是 1
容易被忽略的边界行为:NULL 怎么处理
CUME_DIST() 对 NULL 的处理依赖数据库实现,但主流行为一致:默认 NULLS LAST(即 NULL 排在最后),且 NULL 之间视为相等。
例如:ORDER BY score DESC 下,所有 score IS NULL 的行会排在最末,它们的 CUME_DIST() 值相同,等于“非 NULL 行数 + 1”除以总行数(不是 1)。
- 想让
NULL排最前?显式写ORDER BY score DESC NULLS FIRST(PostgreSQL/Oracle/SQL Server 支持;MySQL 不支持NULLS FIRST/LAST语法) - 如果整列全是
NULL,所有行CUME_DIST()= 1(因为“≤ NULL”的行就是全部) - 在聚合类分析中,若业务上
NULL代表“未成交”,通常应先WHERE score IS NOT NULL过滤,避免扭曲分布意义
CUME_DIST() 得到的是“有多少比例的人分数 ≤ 当前人”,而不是“当前人排第几百分位”;后者更适合用 PERCENT_RANK()。










