如何按客户分区计算月度订单的历史累计总和?
解决方法
要实现你要的「每个客户当前月份之前的累计订单总和」,得先把同一客户、同年同月的订单合并,再基于月度总量计算前置累计,具体分两步写SQL:
第一步:聚合月度订单总量
先把原始数据按客户、年份、月份分组,算出每个月的总订单数:
SELECT 客户, 年份, 月份, SUM(订单数) AS 月度订单数 FROM 你的表名 GROUP BY 客户, 年份, 月份 ORDER BY 客户, 年份, 月份;
这一步会得到每个客户每个月的订单总量,示例数据输出如下:
| 客户 | 年份 | 月份 | 月度订单数 |
|---|---|---|---|
| 1544 | 2022 | 4 | 6 |
| 1544 | 2022 | 12 | 1 |
| 1544 | 2023 | 1 | 3 |
第二步:计算月度前置累计总和
基于上面的聚合结果,用窗口函数计算每个月之前的累计总和,注意要明确指定累计范围是当前行之前的所有行,并用COALESCE把第一行的空值转为0:
WITH 月度订单 AS ( SELECT 客户, 年份, 月份, SUM(订单数) AS 月度订单数 FROM 你的表名 GROUP BY 客户, 年份, 月份 ) SELECT 客户, 年份, 月份, COALESCE( SUM(月度订单数) OVER ( PARTITION BY 客户 ORDER BY 年份, 月份 ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ), 0 ) AS 累计订单数 FROM 月度订单 ORDER BY 客户, 年份, 月份;
执行后就能得到你想要的结果:
| 客户 | 年份 | 月份 | 累计订单数 |
|---|---|---|---|
| 1544 | 2022 | 4 | 0 |
| 1544 | 2022 | 12 | 6 |
| 1544 | 2023 | 1 | 7 |
为什么你之前的方法不对?
lag()函数只能获取上一行的单个值,没法直接累加所有之前行的总和;而单纯用SUM() OVER ()如果不指定范围,默认会包含当前行的数值,得到的是包含当月的累计,不符合你的需求。必须通过ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING明确指定累计范围是当前行之前的所有行,才能得到正确的前置累计值。
内容的提问来源于stack exchange,提问作者WhoIsKi
相关产品推荐
相关产品推荐

