如何使用 MySQL 合并连续的日期和时间行

How to merge consecutive rows of date and time using MySQL

我有一个关注table(查看)

+-------+-------------+-------------+
| 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 |
+-------+-------------+-------------+

我正在尝试找到一种创建 SQL 语句的方法,该语句将执行以下操作:合并具有连续日期和时间的数据(30 分钟间隔)

从我的 SQL 的初级到初级中级能力,我未能正确使用 GROUP BY。期待答案或方向。 再次感谢

结果应该是:

+-------+-------------+-------------+
| Data  |     Date    |    Time     |
+-------+-------------+-------------+
| Data1 |  2020-08-19 |    13:00:00 |
| Data1 |  2020-08-21 |    07:00:00 |
| Data2 |  2020-08-20 |    08:00:00 |
+-------+-------------+-------------+

您可以使用 window 功能。这个想法是使用 window 总和来创建相邻记录组,每当两个连续记录之间的差异超过 30 分钟时,总和就会递增。

select data, min(dt) start_dt,max(dt) end_dt, count(*) cnt
from (
    select
        t.*,
        sum(lag_dt is not null and dt > lag_dt + interval 30 minute)
            over(partition by data order by dt) grp
    from (
        select
            t.*,
            lag(dt) over(partition by data order by dt) lag_dt
        from (
            select t.*, concat(date, ' ', time) dt 
            from mytable t
        ) t
    ) t
) t
group by data, grp
order by min(dt)

请注意,将日期和时间存储在两个单独的列中不是一个好习惯;我添加了额外的嵌套级别以生成 datetime 值。

我们可以用日期算法消除一层嵌套(这里,间隔必须正好是30分钟):

select data, min(dt) start_dt,max(dt) end_dt, count(*) cnt
from (
    select 
        t.*,
        row_number() over(partition by data order by dt) rn
    from (
        select t.*, concat(date, ' ', time) dt 
        from mytable t
    ) t
) t
group by data, dt - interval (rn * 30) minute
order by min(dt)

具有LAG()window功能:

select Data, Date, Time
from (
  select *,
      concat(Date, ' ', Time) - interval 30 minute <= 
      lag(concat(Date, ' ', Time)) over (partition by Data order by Date, Time) flag
  from tablename  
) t
where coalesce(flag, 0) = 0
order by Data, Date, Time

参见demo
结果:

> Data  | Date       | Time    
> :---- | :--------- | :-------
> Data1 | 2020-08-19 | 13:00:00
> Data1 | 2020-08-21 | 07:00:00
> Data2 | 2020-08-20 | 08:00:00

为 postgres 更新

select Data, Date, Time
from (
  select *,
      Date+ Time - interval '00:30' <= 
      lag(Date+ Time,1) over (partition by Data order by Date+Time) flag
  from tablename  
) T
where flag is null or  flag is false
order by Data, Date, Time

Demo