
本文介绍如何通过 sql 实现按月份及 site_id 分组,计算每个站点每月 energy 字段的极差(max - min),并正确关联站点映射表,避免遗漏分组导致的聚合错误。
本文介绍如何通过 sql 实现按月份及 site_id 分组,计算每个站点每月 energy 字段的极差(max - min),并正确关联站点映射表,避免遗漏分组导致的聚合错误。
在实际能源监控或物联网数据分析场景中,常需统计各站点(如医院、诊所等)每月用电量的波动范围,即 MAX(energy) - MIN(energy)。但若直接使用聚合函数而未配合 GROUP BY,SQL 会将全量数据压缩为单行结果,无法体现“每站每月”的粒度要求——这正是原始查询仅返回一行(result_energy = 50)的根本原因。
要达成目标输出(如 2022-07 月 Med 站点极差为 10,2022-08 月 Med 站点极差为 40),必须明确两个分组维度:年月周期 和 站点标识。注意:仅用 MONTH(timeIn) 不足以区分不同年份的同月(如 2022-07 与 2023-07),推荐使用 DATE_FORMAT(timeIn, '%Y-%m') 保证时间维度唯一性;同时需保留 site_id 以支持多站点并行分析。
以下是优化后的标准 SQL 查询:
SELECT DATE_FORMAT(t2.timeIn, '%Y-%m') AS month_year, t1.site_id, t1.site_name, MAX(t2.energy) - MIN(t2.energy) AS result_energy, MAX(t2.timeIn) AS latest_timeIn -- 可选:记录该月最后一条数据时间 FROM Electric.site_map_pae AS t1 INNER JOIN Electric.electric AS t2 ON t1.site_id = t2.site_id WHERE t1.off_id = '3' AND t2.timeIn >= '2022-01-01 00:00:00' AND t2.timeIn <= '2022-12-31 23:59:59' GROUP BY DATE_FORMAT(t2.timeIn, '%Y-%m'), t1.site_id, t1.site_name ORDER BY month_year, t1.site_id;
✅ 关键改进说明:
- 使用
DATE_FORMAT(t2.timeIn, '%Y-%m')替代MONTH(),确保跨年度数据不被错误合并; -
GROUP BY显式包含t1.site_id和t1.site_name(后者增强可读性),杜绝隐式分组歧义; - 移除无意义的
DISTINCT(MAX/MIN本身无视重复值,加DISTINCT反而可能引发兼容性问题); -
ORDER BY提升结果可读性,便于人工核对; -
latest_timeIn作为辅助字段,可用于定位极值发生时间(若需精确到某条记录,应改用窗口函数)。
⚠️ 注意事项:
- 若
timeIn字段存在 NULL 值,MAX/MIN会自动忽略,但建议前置清洗或添加WHERE t2.timeIn IS NOT NULL; -
off_id = '3'是字符串匹配,请确认字段类型;若为整型,应写为off_id = 3避免隐式转换开销; - 大数据量下,务必为
electric.timeIn和electric.site_id字段建立联合索引(如INDEX idx_site_time (site_id, timeIn)),显著提升 JOIN 与 GROUP BY 性能。
通过以上结构化查询,即可精准输出每个站点在每自然月内的用电量波动幅度,为能耗异常检测、设备运行评估提供可靠的数据基础。

















