如何使用MySQL计算每日重置数据的累计值?
纯SQL实现忽略每日重置的累计读数
没问题!完全可以用纯SQL实现你Matlab循环的效果,核心思路是找出所有每日重置的节点,把每个重置前的最后值累加给后续所有记录。我来一步步给你拆解方案:
完整SQL代码
WITH ordered_data AS ( -- 第一步:按时间排序,给每行添加上一行的读数和时间,用于判断重置点 SELECT DateTime, reading, LAG(reading) OVER (ORDER BY DateTime) AS prev_reading, LAG(DateTime) OVER (ORDER BY DateTime) AS prev_datetime FROM daily_data WHERE DateTime BETWEEN '你的起始日期' AND '你的结束日期' -- 替换成你的DateA和DateB ), reset_increments AS ( -- 第二步:找出所有需要累加的增量值(即每次重置前的最后读数) SELECT DateTime AS reset_time, prev_reading AS increment_value FROM ordered_data -- 判断重置的条件:要么跨日期(每日重置的典型特征),要么当前读数比前一行小(应对同一天内意外重置的情况) WHERE prev_reading IS NOT NULL AND (DATE(DateTime) != DATE(prev_datetime) OR reading < prev_reading) ) -- 第三步:给每行加上所有之前重置点的增量总和,得到累计值 SELECT od.DateTime, od.reading AS original_reading, od.reading + COALESCE(SUM(ri.increment_value), 0) AS cumulative_reading FROM ordered_data od LEFT JOIN reset_increments ri ON ri.reset_time <= od.DateTime GROUP BY od.DateTime, od.reading, od.prev_reading, od.prev_datetime ORDER BY od.DateTime;
代码逻辑解释
ordered_dataCTE:先按时间顺序排列所有数据,通过LAG()窗口函数获取前一行的读数和时间,这样我们能轻松判断哪里发生了重置。reset_incrementsCTE:筛选出所有重置事件对应的增量值——当跨日期(每日重置的典型特征)或者当前读数突然小于前一行(说明触发了重置)时,前一行的读数就是需要累加到后续所有记录的增量。- 最终查询:把每一行和所有在它之前的重置增量做左连接,求和这些增量后加上当前读数,就得到了忽略每日重置的累计值,和你Matlab循环的输出完全一致。
示例验证
假设你的原始数据是:
| DateTime | reading |
|---|---|
| 2024-01-01 08:00 | 10 |
| 2024-01-01 12:00 | 25 |
| 2024-01-01 18:00 | 30 |
| 2024-01-02 09:00 | 5 |
| 2024-01-02 14:00 | 15 |
| 2024-01-03 08:30 | 3 |
运行SQL后得到的累计值:
| DateTime | original_reading | cumulative_reading |
|---|---|---|
| 2024-01-01 08:00 | 10 | 10 |
| 2024-01-01 12:00 | 25 | 25 |
| 2024-01-01 18:00 | 30 | 30 |
| 2024-01-02 09:00 | 5 | 35 |
| 2024-01-02 14:00 | 15 | 45 |
| 2024-01-03 08:30 | 3 | 48 |
这个结果和你Matlab循环计算的完全相同:每次重置后,后续所有记录都加上了重置前的最后读数。
额外提示
- 如果你的MySQL版本低于8.0(不支持CTE和窗口函数),可以把CTE替换成子查询,逻辑是一样的,只是写法更繁琐。
- 给
DateTime字段加索引,这样大表查询时排序和连接的效率会高很多。 - 如果你的读数偶尔会有小波动(不是重置),可以把重置判断条件简化为
DATE(DateTime) != DATE(prev_datetime),只按日期跨天来判断重置,这样更精准。
内容的提问来源于stack exchange,提问作者Liesev
相关产品推荐
相关产品推荐

