如何无需循环用SQL实现月度credit/debit合计与累计求和?
无需循环的简便实现:使用窗口函数
当然有!不用循环的话,**窗口函数(Window Functions)**是最直接高效的解决方案,完全能满足你的需求,下面我给你拆解步骤和示例代码:
核心思路
分两步完成计算:
- 先按月度聚合数据,算出每个月的信用合计、借方合计,以及当月的最大日期;
- 基于月度聚合结果,用累计求和窗口函数计算累计值(progressive credit/debit)。
示例SQL代码(通用逻辑,适配多数关系型数据库)
WITH monthly_agg AS ( -- 第一步:按月度聚合基础数据 SELECT -- 截断日期到月份,用于分组(不同数据库语法略有差异,见下方说明) DATE_TRUNC('month', dat_dt) AS month_period, MAX(dat_dt) AS max_date, SUM(credit) AS cr_sum, SUM(debit) AS dr_sum FROM T1 GROUP BY DATE_TRUNC('month', dat_dt) ) -- 第二步:计算累计值 SELECT max_date, cr_sum, SUM(cr_sum) OVER (ORDER BY month_period) AS "progressive credit", dr_sum, SUM(dr_sum) OVER (ORDER BY month_period) AS "progressive debit" FROM monthly_agg ORDER BY month_period;
代码细节说明
月度聚合CTE(
monthly_agg):DATE_TRUNC('month', dat_dt):将日期截断到当月的起始日期(比如22-02-2019会变成2019-02-01),用来作为分组依据。MAX(dat_dt):提取当月的最大日期,对应你要的max_date字段。SUM(credit)/SUM(debit):分别计算当月的信用和借方总和。
累计值计算:
SUM(cr_sum) OVER (ORDER BY month_period):按月份顺序对cr_sum做累计求和,自动把当月值加上之前所有月份的总和,得到progressive credit;借方累计值的逻辑完全一致。
不同数据库的日期函数适配
如果你的数据库不支持DATE_TRUNC,可以替换成对应语法:
- MySQL:用
DATE_FORMAT(dat_dt, '%Y-%m')来分组 - SQL Server:用
DATEFROMPARTS(YEAR(dat_dt), MONTH(dat_dt), 1)来分组 - Oracle:用
TRUNC(dat_dt, 'MM')来分组
验证结果
代入你提供的示例数据,运行后会得到完全符合期望的输出:
| max_date | cr_sum | progressive credit | dr_sum | progressive debit |
|---|---|---|---|---|
| 25-02-2019 | 40 | 40 | 65 | 65 |
| 13-03-2019 | 150 | 190 | 50 | 115 |
内容的提问来源于stack exchange,提问作者Nidheesh
相关产品推荐
相关产品推荐

