如何按年度每月计算YTD累计值?SQL实现方案咨询
实现当年累计求和(YTD)的SQL方案
嘿,这个需求其实很典型,用**窗口函数(Window Function)**就能轻松搞定!核心是按年份对数据分区,让每年的累计计算独立进行,再在每个分区内按时间顺序累加oValue,下面给你详细的思路和不同数据库的具体实现:
核心实现思路
- 分区(Partition):按数据的年份分组,确保每年的累计求和从1月重新开始,不会和其他年份的数值混淆
- 排序(Order):在每个年份分区内,按日期
oDate从小到大排序,保证累计是按时间顺序进行的 - 累计求和:用窗口函数的
SUM()结合分区和排序规则,计算从当年第一个月到当前月的oValue总和
各数据库具体SQL示例
1. SQL Server / Azure SQL
利用YEAR()函数提取年份,窗口函数语法简洁直观:
SELECT oDate, oValue, -- 按年份分区,按日期排序,累计求和 SUM(oValue) OVER ( PARTITION BY YEAR(oDate) ORDER BY oDate -- ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 是默认规则,可省略 ) AS YTD FROM YourTableName;
2. MySQL 8.0+
MySQL 8.0及以上版本支持窗口函数,语法和SQL Server类似:
SELECT oDate, oValue, SUM(oValue) OVER ( PARTITION BY YEAR(oDate) ORDER BY oDate ) AS YTD FROM YourTableName;
如果是MySQL 5.x(不支持窗口函数),可以用自连接的方式实现:
SELECT t1.oDate, t1.oValue, SUM(t2.oValue) AS YTD FROM YourTableName t1 INNER JOIN YourTableName t2 ON YEAR(t1.oDate) = YEAR(t2.oDate) AND t2.oDate <= t1.oDate GROUP BY t1.oDate, t1.oValue ORDER BY t1.oDate;
3. PostgreSQL
用EXTRACT()或DATE_PART()提取年份,注意转换为整数类型避免分区异常:
SELECT oDate, oValue, SUM(oValue) OVER ( PARTITION BY EXTRACT(YEAR FROM oDate)::INTEGER ORDER BY oDate ) AS YTD FROM YourTableName;
验证说明
因为你的表每月仅包含一条数据,上述所有方案都能准确计算出当年截至对应月份的累计总和,且每年1月会自动重置累计值,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Haminteu




