cume_dist计算≤当前行值的行数占比,结果∈(0,1]且首行>0;percent_rank用(行号−1)/(n−1),首行恒为0。两者均需order by,cume_dist适用于“多少比例订单≤当前金额”等业务场景。

什么是 CUME_DIST,它和 PERCENT_RANK 有什么区别
CUME_DIST 返回当前行在分组内的「累积分布」,即值 ≤ 当前行的行数 ÷ 分组总行数。结果范围是 (0, 1],最小值一定 > 0(哪怕排第一,也是 1/N),而 PERCENT_RANK 是 (行号−1)/(N−1),首行必为 0。
对订单分析来说,CUME_DIST 更贴近「有多少比例的订单金额 ≤ 当前订单」这个业务问题——比如某笔订单 CUME_DIST = 0.72,说明 72% 的订单金额都不超过它。
- 必须配合
ORDER BY使用,否则报错:Window function 'CUME_DIST' requires an OVER clause with ORDER BY - 不支持
PARTITION BY时省略ORDER BY;即使只按时间分区,也得指定排序字段(如amount) - NULL 值默认排最前(
NULLS FIRST),若想把 NULL 当作未知值排除,先用WHERE amount IS NOT NULL
直接计算全量订单金额的累积分布
最常见需求:看所有订单按金额从小到大排列后,每个金额对应的覆盖比例。
SELECT order_id, amount, CUME_DIST() OVER (ORDER BY amount) AS cum_dist FROM orders WHERE amount IS NOT NULL;
注意点:
- 结果中相同
amount的多行会得到相同的cum_dist值(因为是「≤ 当前值」的累计比例) - 如果想按「金额区间」聚合(比如每 100 元一段),不能直接在窗口函数外
GROUP BY ROUND(amount, -2)—— 窗口函数必须在GROUP BY之后执行,要先用 CTE 或子查询算好原始累积值,再聚合 - SQL Server 2012+ 支持,但 Azure SQL 和 Parallel Data Warehouse 同样可用;SQL Server 2008 不支持
按客户分组看各自订单金额分布
当你要比较不同客户的消费能力分布时,需用 PARTITION BY customer_id:
SELECT
customer_id,
order_id,
amount,
CUME_DIST() OVER (
PARTITION BY customer_id
ORDER BY amount
) AS cum_dist_per_customer
FROM orders
WHERE amount IS NOT NULL;
关键细节:
- 每个客户内部独立计算:客户 A 有 5 笔订单,其
cum_dist取值只能是 0.2, 0.4, 0.6, 0.8, 1.0(或合并重复值后更少) - 若某客户只有 1 笔订单,
cum_dist恒为 1.0 —— 这符合定义,但业务上可能需要过滤掉单笔订单客户再分析 -
PARTITION BY字段必须出现在SELECT或WHERE中,否则无法关联上下文;不要依赖ORDER BY外部排序来“补救”分区逻辑
和直方图、NTILE 配合使用的实际限制
CUME_DIST 是连续分布,而 NTILE(4) 是强行四等分(可能切在金额断点中间),两者语义不同,混用容易误导。
例如想标出「高价值订单(cum_dist > 0.9)」,直接写 WHERE CUME_DIST() OVER (...) > 0.9 会报错 —— 窗口函数不能出现在 WHERE。必须用子查询或 CTE:
WITH ranked AS (
SELECT
order_id,
amount,
CUME_DIST() OVER (ORDER BY amount) AS cum_dist
FROM orders
WHERE amount IS NOT NULL
)
SELECT * FROM ranked WHERE cum_dist > 0.9;
另外要注意:
-
CUME_DIST对数据倾斜敏感:如果大量订单集中在某个低价区间,开头的累积比例会上升很快,图形上表现为陡坡,不是均匀曲线 - 它不接受
ROWS BETWEEN等帧定义,始终作用于整个分区(或全集),没法做滑动窗口式累积分布 - 如果后续要导出到 Power BI 做动态切片,建议在 SQL 层就加
FORMAT(cum_dist, 'P2')转成百分比字符串,避免前端格式化误差
真正难的不是写对语法,而是想清楚你到底要回答「多少订单 ≤ 某个金额」,还是「某个金额处于整体什么分位」——前者用 CUME_DIST,后者通常用 PERCENT_RANK 或 PERCENTILE_CONT。










