如何使用 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
我有一个关注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