MySQL如何按分钟聚合15秒频率数据并解决同分钟重复记录问题
问题原因
你使用round(unix_timestamp(timestamp)/(1 * 60))作为分组键是出现同分钟多条记录的核心原因:round()是四舍五入计算逻辑,同一分钟内秒数小于30的时间戳和秒数大于等于30的时间戳,除以60后四舍五入的结果会落在两个不同分组,最终导致同一分钟被拆分出两条记录。
解决方案
推荐使用更直观的分钟级时间截断作为分组依据,避免数值计算的逻辑误差,根据你使用的MySQL版本选择对应方案即可:
方案1:MySQL 8.0+ 版本(窗口函数实现)
如果需要指定每个分钟返回哪条记录(比如最早/最晚的一条),用窗口函数逻辑最清晰,以下是取每分钟最早一条记录的写法:
WITH ranked_data AS ( SELECT `timestamp`, value, -- 按分钟分组,给同分钟内的记录按时间先后排序 ROW_NUMBER() OVER (PARTITION BY DATE_FORMAT(`timestamp`, '%Y-%m-%d %H:%i') ORDER BY `timestamp` ASC) AS rn FROM table_1 ) -- 取每个分钟排序后的第一条记录 SELECT `timestamp`, value FROM ranked_data WHERE rn = 1;
方案2:MySQL 5.x 版本(子查询关联实现)
低版本不支持窗口函数的情况下,可以先聚合拿到每个分钟的目标时间戳,再关联原表取对应字段:
SELECT t1.`timestamp`, t1.value FROM table_1 t1 INNER JOIN ( -- 先取每个分钟的最早时间戳 SELECT MIN(`timestamp`) AS min_ts FROM table_1 GROUP BY DATE_FORMAT(`timestamp`, '%Y-%m-%d %H:%i') ) t2 ON t1.`timestamp` = t2.min_ts;
如果你不需要指定返回同分钟内的某条记录,只需要确保每分钟只有一条,也可以直接修改你原来的写法,把round替换为向下取整的floor即可:
select `timestamp`, value from table_1 group by floor(unix_timestamp(timestamp)/(1 * 60));
内容的提问来源于stack exchange,提问作者Ganesh Gudghe
相关产品推荐
相关产品推荐

