【问题标题】:How to merge consecutive rows of date and time using MySQL如何使用 MySQL 合并连续的日期和时间行
【发布时间】:2020-12-08 17:19:30
【问题描述】:

我有一个下表(视图)

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

【问题讨论】:

  • "合并数据" - 你需要定义合并规则。
  • MySQL 版本到底是什么?
  • Mysql版本为8.0.21

标签: mysql sql datetime window-functions gaps-and-islands


【解决方案1】:

带有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, 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

【讨论】:

  • 很好用。请问如果我在 MariaDB 中尝试这些 SQL 是否仍然有效?
  • @StoledInk MariaDB 想要将日期时间字符串转换为日期时间:dbfiddle.uk/…
【解决方案2】:

您可以使用窗口函数。这个想法是使用窗口总和创建相邻记录组,每次两个连续记录之间的差异超过 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)

【讨论】:

    【解决方案3】:

    为 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-14
      • 2017-02-12
      • 1970-01-01
      • 2013-03-24
      • 1970-01-01
      • 2010-12-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多