【问题标题】:MySQL Group from quarters to periodsMySQL 组从季度到期间
【发布时间】:2020-09-16 20:19:05
【问题描述】:

我有一张这样的桌子:

Person smallint(5)  act_time datetime
1   2020-05-29 07:00:00
1   2020-05-29 07:15:00
1   2020-05-29 07:30:00
2   2020-05-29 07:15:00
2   2020-05-29 07:30:00
1   2020-05-29 10:30:00
1   2020-05-29 10:45:00

上面的表格是一个有 2 个不同的人的例子,他们工作的每个季度都有一行...

在 MySQL 中,将此表“转换”为另一个表的最佳方法是什么,其中有一列用于“人”,一列用于“开始”,一列用于“停止”。

所以结果是这样的:

Person  Start   Stop
1   2020-05-29 07:00:00   2020-05-29 07:45:00
2   2020-05-29 07:15:00   2020-05-29 07:45:00
1   2020-05-29 10:30:00   2020-05-29 11:00:00

我曾尝试对同一个原始表进行左连接,但没有成功...

谢谢。

感谢您的回复。我现在已经用上面的表格尝试过了——不幸的是它没有给出那个结果...... 我的 sql 字符串是:

select person,min(act_time) start_date,max(act_time) end_date from (select t.*,row_number() over(order by act_time) rn1,row_number() over(partition by person order by act_time) rn2 from test t) t group by person, rn1 - rn2 order by min(act_time)

But the result it generates is:
1 29-05-2020 07:00:00 29-05-2020 07:15:00
2 29-05-2020 07:15:00 29-05-2020 07:15:00
1 29-05-2020 07:30:00 29-05-2020 07:30:00
2 29-05-2020 07:30:00 29-05-2020 07:30:00
1 29-05-2020 10:30:00 29-05-2020 10:45:00

它应该像 3 行的结果。因此,当同一个人的行之间的间隔超过 15 分钟时,它应该创建一个新行。

【问题讨论】:

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


【解决方案1】:

这是一个孤岛问题。我不确定为什么 GMB 的解决方案不起作用,但这应该:

select person, min(act_date) as start_date,
       max(act_date) + interval 15 minute as end_date
from (select t.*,
             sum(case when prev_act_date >= act_date - interval 15 minute then 0 else 1 end) over
                 (partition by person order by act_date) as grp
      from (select t.*,
                   lag(act_date) over (partition by person order by act_date) as prev_act_date
            from t
           ) t
     ) t
group by person, grp
order by min(act_date)

【讨论】:

  • 这个字符串做到了。谢谢你的帮助:-)
【解决方案2】:

这是一个空白和孤岛问题。您可以使用窗口函数来解决它(仅在 MySQL 8.0 中可用):

select 
    person,
    min(act_date) start_date,
    max(act_date) end_date
from (
    select
        t.*,
        sum(act_date <> lag_act_date + interval 15 minute)
            over(partition by person order by act_date) grp
    from (
        select 
            t.*,
            lag(act_date) 
                over(partition by person order by act_date) lag_act_date
        from mytable t
    ) t
) t
group by person, grp
order by min(act_date)

这个想法是使用累积和来构建相邻记录组:每次间隔不是 15 分钟时,总和就会增加。

【讨论】:

  • 感谢您的回复。不幸的是,它没有返回所需的结果......我已经在问题中添加了它返回的结果。
猜你喜欢
  • 2013-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
  • 1970-01-01
相关资源
最近更新 更多