如何使用MySQL合并30分钟间隔的连续日期时间行
解决连续30分钟间隔数据的起始行提取问题
嘿,我明白你现在的需求啦——要把同Data分组下,那些按30分钟连续间隔排列的数据只保留每组的第一行。别担心,这个问题用基础到进阶的SQL知识就能解决,我给你两种实用的方案,一步步来解释:
先明确你的数据和目标
原始数据表(视图)
| Data | Date | Time |
|---|---|---|
| Data1 | 2020-08-19 | 13:00:00 |
| Data1 | 2020-08-19 | 13:30:00 |
| Data1 | 2020-08-19 | 14:00:00 |
| Data1 | 2020-08-21 | 07:00:00 |
| Data1 | 2020-08-21 | 07:30:00 |
| Data2 | 2020-08-20 | 08:00:00 |
| Data2 | 2020-08-20 | 08:30:00 |
期望结果
| Data | Date | Time |
|---|---|---|
| Data1 | 2020-08-19 | 13:00:00 |
| Data1 | 2020-08-21 | 07:00:00 |
| Data2 | 2020-08-20 | 08:00:00 |
方案一:用NOT EXISTS(适合大部分SQL数据库,新手友好)
这个思路很直接:找出那些「往前推30分钟后,没有同一Data的对应记录」的行——这些就是每个连续序列的起始行。
首先,我们需要把Date和Time合并成一个完整的 datetime 字段,方便计算时间差。不同数据库的合并方式略有不同,我会在代码里标注通用写法:
SELECT t1.Data, t1.Date, t1.Time FROM your_table t1 WHERE NOT EXISTS ( SELECT 1 FROM your_table t2 WHERE t2.Data = t1.Data -- 这里替换成你数据库的时间合并+减30分钟逻辑 AND t2.full_datetime = DATEADD(MINUTE, -30, STR_TO_DATE(CONCAT(t1.Date, ' ', t1.Time), '%Y-%m-%d %H:%i:%s') ) );
细节说明:
- 把
your_table替换成你实际的表/视图名 - 时间合并逻辑可以根据数据库调整:
- MySQL:
STR_TO_DATE(CONCAT(Date, ' ', Time), '%Y-%m-%d %H:%i:%s') - SQL Server:
CAST(Date AS DATETIME) + CAST(Time AS DATETIME) - PostgreSQL:
(Date || ' ' || Time)::TIMESTAMP
- MySQL:
NOT EXISTS的逻辑:如果找不到同一Data、且时间刚好是当前行前30分钟的记录,那当前行就是新序列的起点,需要保留
方案二:用窗口函数LAG(进阶高效版)
如果你的数据库支持窗口函数(比如MySQL 8.0+、SQL Server、PostgreSQL等),用LAG函数可以更直观地对比当前行和前一行的时间差:
WITH ranked_data AS ( SELECT Data, Date, Time, -- 合并日期时间,替换成你数据库的对应写法 STR_TO_DATE(CONCAT(Date, ' ', Time), '%Y-%m-%d %H:%i:%s') AS full_datetime, -- 获取同一Data组中前一行的时间 LAG(STR_TO_DATE(CONCAT(Date, ' ', Time), '%Y-%m-%d %H:%i:%s')) OVER (PARTITION BY Data ORDER BY full_datetime) AS prev_datetime FROM your_table ) SELECT Data, Date, Time FROM ranked_data WHERE -- 组内第一行(没有前一行),必然是起始行 prev_datetime IS NULL -- 和前一行的时间差不是30分钟,说明是新序列的起点 OR TIMESTAMPDIFF(MINUTE, prev_datetime, full_datetime) != 30;
细节说明:
- 先用
WITH子句(CTE)给每个Data分组,按时间排序,然后用LAG拿到前一行的时间prev_datetime - 筛选逻辑很清晰:要么是组里的第一行,要么和前一行的间隔不是30分钟——这两类都是我们要保留的起始行
- 测试时可以单独运行CTE部分,查看
prev_datetime是否正确,方便排查问题
内容的提问来源于stack exchange,提问作者StoledInk
相关产品推荐
相关产品推荐

