SQL关联MeterReading表查询当月及上月抄表读数实现方案
问题原因
- 核心错误是子查询内的关联年月计算逻辑完全颠倒:你的思路是将子查询的「上月记录」计算出它对应的「当月年月」,再和主表的当月记录关联,但判断条件写反了:你判断的是当前月为1的场景,实际应该判断当前月为12的场景。当前逻辑会把2021年1月的记录标记为匹配2022年12月的主表记录,完全不符合业务逻辑,导致绝大多数记录关联不上。
- 输出字段冗余,不需要返回TMR表的MeterID、YV2、MV2等中间计算字段,只需保留上月的读数类字段即可。
正确实现方案
方案1:通用自关联写法(兼容所有SQL版本)
不需要额外写子查询做年月转换,直接在关联条件里分场景匹配上月即可,逻辑清晰不易出错:
SELECT MR.MeterID, MR.YearVal, MR.MonthVal, MR.ReadingVal, MR.UsingVal, TMR.ReadingVal AS PrevVal, TMR.UsingVal AS PrevUsingVal, 0 AS DelFlag FROM MeterReading MR LEFT JOIN MeterReading TMR ON MR.MeterID = TMR.MeterID AND ( -- 非1月的情况:关联同年上月 (MR.MonthVal > 1 AND TMR.YearVal = MR.YearVal AND TMR.MonthVal = MR.MonthVal - 1) OR -- 1月的情况:关联上年12月 (MR.MonthVal = 1 AND TMR.YearVal = MR.YearVal - 1 AND TMR.MonthVal = 12) ) ORDER BY MR.YearVal, MR.MonthVal
方案2:窗口函数写法(兼容MySQL8.0+、PostgreSQL、SQL Server等支持窗口函数的数据库)
用LAG偏移函数直接取同个电表按年月排序的上一条记录值,自动处理跨年逻辑,代码更简洁、性能更优:
SELECT MeterID, YearVal, MonthVal, ReadingVal, UsingVal, LAG(ReadingVal) OVER (PARTITION BY MeterID ORDER BY YearVal, MonthVal) AS PrevVal, LAG(UsingVal) OVER (PARTITION BY MeterID ORDER BY YearVal, MonthVal) AS PrevUsingVal, 0 AS DelFlag FROM MeterReading ORDER BY YearVal, MonthVal
内容的提问来源于stack exchange,提问作者SANGEETH SUBRAMONIAM
相关产品推荐
相关产品推荐

