如何使用SQL窗口函数实现按月滚动的3个月累计求和功能
滚动3个月求和需求的窗口函数实现方案
结论
该需求完全可以通过标准窗口函数实现,无需额外的自定义逻辑或表关联操作。
实现思路
核心逻辑是先对齐月度边界(统一按每月1日作为计算基准),再通过窗口的范围规则定义3个月的滚动窗口,核心分为两步:
- 先将所有日期映射为对应月份的1日,对齐计算基准
- 基于对齐后的月度维度,定义滑动窗口完成求和
通用SQL示例
以下示例基于标准SQL语法,不同数据库的时间处理函数可根据实际使用的产品调整:
方案1:生成月度维度的滚动求和结果(和Excel示例效果一致)
WITH monthly_total AS ( -- 先聚合得到每个月的名义金额总和 SELECT -- 不同数据库替换为对应取当月1日的函数: -- PostgreSQL: date_trunc('month', date)::date -- MySQL 8.0+: DATE_FORMAT(date, '%Y-%m-01') -- SQL Server: DATEFROMPARTS(YEAR(date), MONTH(date), 1) date_trunc('month', date)::date AS stat_month, SUM(notional_amount) AS month_total FROM 你的表名 GROUP BY stat_month ) SELECT stat_month, month_total, -- 窗口计算最近3个月(含当前月)的总和 SUM(month_total) OVER( ORDER BY stat_month RANGE BETWEEN INTERVAL '2 month' PRECEDING AND CURRENT ROW ) AS rolling_3month_sum FROM monthly_total ORDER BY stat_month;
方案2:在原始逐日数据上展示对应月度滚动值
如果需要每一行原始数据都显示所属月对应的滚动3个月总和,可直接在明细层计算:
SELECT date, notional_amount, SUM(notional_amount) OVER( ORDER BY date_trunc('month', date)::date RANGE BETWEEN INTERVAL '2 month' PRECEDING AND CURRENT ROW ) AS rolling_3month_sum FROM 你的表名;
特殊数据库兼容说明
部分数据库(如SQL Server)不支持在RANGE子句中使用时间间隔,可先将月份转换为连续数字,再用ROWS定义窗口:
WITH month_num_calc AS ( SELECT date, notional_amount, YEAR(date) * 12 + MONTH(date) AS month_sequence FROM 你的表名 ) SELECT date, notional_amount, SUM(notional_amount) OVER( ORDER BY month_sequence ROWS BETWEEN 2 PRECEDING AND CURRENT ROW ) AS rolling_3month_sum FROM month_num_calc;
内容的提问来源于stack exchange,提问作者Lukasz
相关产品推荐
相关产品推荐

