
本文讲解如何通过 sql 对多站点、跨月份的能耗数据进行分组聚合,精确计算每个站点每月的能耗最大值与最小值之差,并正确关联站点配置表。
本文讲解如何通过 sql 对多站点、跨月份的能耗数据进行分组聚合,精确计算每个站点每月的能耗最大值与最小值之差,并正确关联站点配置表。
在实际能源监控系统中,常需按站点(site_id)和自然月统计关键指标——例如单月能耗极差(MAX(energy) - MIN(energy)),以反映该站点当月用电波动幅度。但若忽略分组逻辑,仅使用聚合函数而未指定 GROUP BY,SQL 将默认对全量数据做全局聚合,导致仅返回一行结果,无法满足“每站每月”的分析粒度。
要实现目标输出(即每个站点、每个月份独立计算极差),必须明确两个维度的分组依据:月份 和 站点标识。注意:原始查询中 timeIn 是 DATETIME 类型,直接 GROUP BY timeIn 会导致按精确到秒的时间点分组,完全失效;应提取年月信息。更健壮的做法是使用 YEAR(timeIn) 和 MONTH(timeIn) 联合分组,或更推荐使用 DATE_FORMAT(timeIn, '%Y-%m') 保证年月完整性(避免不同年份同月被错误合并)。
以下是修正后的标准 SQL 查询:
SELECT DATE_FORMAT(t2.timeIn, '%Y-%m') AS month, 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, t1.site_id;
✅ 关键优化说明:
- 使用
DATE_FORMAT(timeIn, '%Y-%m')替代MONTH(timeIn),确保 2022-07 与 2023-07 不被混为一月; -
GROUP BY必须包含所有非聚合字段(如t1.site_id,t1.site_name),否则 MySQL 8.0+ 严格模式会报错; -
MAX(timeIn)用于定位该组内最新记录时间,便于后续溯源(如示例中2022-08-09 13:37:23); -
DISTINCT在MIN/MAX中无意义(聚合函数自动忽略重复值),可安全移除,提升可读性与性能。
⚠️ 注意事项:
- 若某站点某月仅有单条记录,则
result_energy = 0(因MAX = MIN),属合理结果; - 时间范围建议用
>=/替代 <code>BETWEEN,避免因毫秒精度引发边界遗漏; - 生产环境强烈建议在
electric.timeIn和electric.site_id上建立联合索引(如INDEX idx_site_time (site_id, timeIn)),大幅提升 JOIN 与分组效率。
通过以上结构化分组与精准关联,即可稳定输出每个站点每月的能耗波动值,为能效诊断与异常识别提供可靠数据基础。

















