SQL Server:用两个聚合函数计算客户分时段月均采购额
解决方案
要计算各时段的月均采购金额,核心是将每个时段的销售额总和除以该时段内唯一的年月组合数量。以下是修改后的SQL代码,同时处理了无数据时段避免除以0的问题:
SELECT c.customer_name, -- PRE时段:2021-04-01之前的月均金额 SUM(CASE WHEN s.date < '2021-04-01' THEN VALUE_USD END) / NULLIF(COUNT(DISTINCT DATE_TRUNC('month', s.date) FILTER (WHERE s.date < '2021-04-01')), 0) AS PRE, -- DURING时段:2021-04-01至2022-03-31的月均金额 SUM(CASE WHEN s.date BETWEEN '2021-04-01' AND '2022-03-31' THEN VALUE_USD END) / NULLIF(COUNT(DISTINCT DATE_TRUNC('month', s.date) FILTER (WHERE s.date BETWEEN '2021-04-01' AND '2022-03-31')), 0) AS DURING, -- POST时段:2022-04-01之后的月均金额 SUM(CASE WHEN s.date > '2022-04-01' THEN VALUE_USD END) / NULLIF(COUNT(DISTINCT DATE_TRUNC('month', s.date) FILTER (WHERE s.date > '2022-04-01')), 0) AS POST FROM SALES as s LEFT JOIN CUSTOMER as c ON s.account_no = c.account_no GROUP BY c.customer_name;
关键改动说明
- DATE_TRUNC('month', s.date):将日期截断到月份,获取唯一的年月组合;部分SQL方言可改用
TO_CHAR(s.date, 'YYYY-MM')实现相同效果。 - FILTER子句:精准统计对应时段内的唯一年月数量,避免跨时段统计干扰。
- NULLIF(..., 0):当某时段无数据时,返回NULL而非触发除以0的错误。
示例数据的期望输出
| customer_name | PRE | DURING | POST |
|---|---|---|---|
| JOHN SMITH | 100 | 233.33 | 300 |
计算逻辑验证
- PRE时段:总销售额300美元,对应3个年月(2020-03、2020-04、2020-05),月均300/3=100。
- DURING时段:总销售额700美元,对应3个年月(2021-04、2021-05、2021-07),月均700/3≈233.33。
- POST时段:总销售额600美元,对应2个年月(2022-05、2022-06),月均600/2=300。
内容的提问来源于stack exchange,提问作者user15260186
相关产品推荐
相关产品推荐

