如何在SQL中使用CUME_DIST函数分析销售额分布的累积概率?

作者:袖梨 2026-06-18
CUME_DIST返回当前行在分区中“小于等于其值的行数占比”,结果范围为(0,1];它基于实际行数计算累积分布,相同值获相同结果,必须配合ORDER BY使用,支持PARTITION BY分组。

什么是 CUME_DIST,它返回什么值?

CUME_DIST 是窗口函数,计算当前行在分区内的「小于等于该行值的行数占比」。它不按排名顺序编号,而是直接给出累积分布比例:最小值对应结果 ≥ 0.0(实际为 1 / 总行数),最大值恒为 1.0。

关键点:CUME_DIST 基于值的大小而非排名位置——相同销售额会得到相同的累积概率,且结果范围严格在 (0, 1] 区间内。

怎么写基础语法才能正确算出销售额累积概率?

必须用 ORDER BY 子句定义排序依据,且不能省略 OVER();否则报错 Window function requires an OVER clause。常见错误是只写 OVER(ORDER BY sales) 却忘了加括号或漏掉排序字段。

  • SELECT product, sales, CUME_DIST() OVER (ORDER BY sales) AS cum_prob FROM orders;
  • 若需分组统计(比如按地区看各自销售额分布),加上 PARTITION BY region
  • 注意:ORDER BY 中不能用别名,必须写原始列名或表达式,如 ORDER BY ABS(sales) 可以,但 ORDER BY s(即使前面写了 sales AS s)会报错

为什么和 PERCENT_RANK 结果不一样?

CUME_DISTPERCENT_RANK 都算累积比例,但算法不同:CUME_DIST = 小于等于当前值的行数 ÷ 总行数;PERCENT_RANK = (排名 − 1)÷(总行数 − 1)。当有重复销售额时,前者对相同值返回相同结果,后者可能因并列排名处理方式不同而产生差异。

例如 5 行数据中,3 行销售额都是 1000,则这三行的 CUME_DIST 都是 3/5 = 0.6;而 PERCENT_RANK 对它们都返回 (2−1)/(5−1) = 0.25(假设并列排第2名)。

实际分析销售额分布时容易忽略的细节

空值(NULL)默认排在最前,会影响累积概率起点。如果销售额字段含 NULLCUME_DIST 会把它们全算进「≤ 当前行值」里,导致第一个非空值的结果偏高。

  • 建议预处理:用 WHERE sales IS NOT NULL 过滤,或用 ORDER BY sales NULLS LAST(PostgreSQL/Oracle 支持,MySQL 8.0+ 不支持该子句)
  • MySQL 8.0+、PostgreSQL、SQL Server、Oracle 都支持 CUME_DIST,但 SQLite 不支持
  • 性能上,大表慎用未建索引的 ORDER BY 列,窗口函数仍会触发全扫描排序

真正影响业务判断的是「你是否理解这个比例是相对于整个窗口的累计覆盖度」,而不是某个分位点的精确估计。

相关文章

精彩推荐