问题描述
我有一张下表(视图)
+-------+-------------+-------------+
| 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到早期的中级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 |
+-------+-------------+-------------+
解决方法
您可以使用窗口功能。这个想法是使用一个窗口总和来创建相邻记录的组,每次两个连续记录之间的差异超过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,count(*) cnt
from (
select
t.*,row_number() over(partition by data order by dt) rn
from (
select t.*,time) dt
from mytable t
) t
) t
group by data,dt - interval (rn * 30) minute
order by min(dt)
,
具有LAG()
窗口功能:
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,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 - 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,Time