如何编写MySQL查询计算年初至今累计平均值并每年重置
解决年初至今累计平均值(每年重置)的MySQL查询方案
没问题,我来帮你搞定这个累计平均值的需求~首先我先假设你的表结构包含日期字段(比如record_date)和需要计算平均值的数值字段(比如metric_value)——要是你实际字段名不一样,直接替换成自己的就行。
核心思路
我们需要实现两个关键逻辑:
- 按年份分区计算:确保每年的累计平均值独立计算,不会和其他年份的数据混淆;
- 1月1日重置为0:对每年1月1日的记录,强制将平均值设为0,之后的记录从年初开始累计计算平均值。
最终查询语句
SELECT record_date, metric_value, -- 处理1月1日重置为0的逻辑,其余日期计算年初至今累计平均 CASE WHEN DAYOFYEAR(record_date) = 1 THEN 0 ELSE AVG(metric_value) OVER ( PARTITION BY YEAR(record_date) -- 按年份分区,每年独立计算 ORDER BY record_date -- 按日期排序,保证累计顺序 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -- 窗口范围:年初到当前行 ) END AS average FROM your_table_name -- 替换成你的实际表名 ORDER BY record_date;
语句细节解释
PARTITION BY YEAR(record_date):把数据按年份拆分成独立的组,这样2023年的累计计算不会包含2024年的数据,完美实现每年重置的效果;ORDER BY record_date:在每个年份组内按日期排序,确保累计计算是从年初到当前行的顺序;ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW:明确指定窗口范围是当前年份的第一条记录到当前行,这其实是AVG()窗口函数的默认行为,但写上更直观易懂;CASE语句:通过DAYOFYEAR(record_date) = 1判断是否是当年1月1日,若是则将average设为0,符合你要求的重置规则。
额外补充
- 如果你的日期字段是
DATETIME类型,只需把record_date换成DATE(record_date)即可,不影响分组和计算; - 如果数值字段可能存在
NULL值,AVG()会自动忽略这些值。要是你需要把NULL当作0来计算,可以把metric_value替换成COALESCE(metric_value, 0); - 要是你希望1月1日的记录显示当天的平均值(而不是0),直接去掉
CASE语句,保留AVG(metric_value) OVER (...) AS average即可。
内容的提问来源于stack exchange,提问作者Robson
相关产品推荐
相关产品推荐

