MySQL Группа от кварталов до периодов - PullRequest
1 голос
/ 29 мая 2020

У меня есть такая таблица:

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 минут, следует создать новый ряд.

Ответы [ 2 ]

0 голосов
/ 29 мая 2020

Это проблема промежутков и островков. Я не уверен, почему решение 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)
0 голосов
/ 29 мая 2020

Это проблема промежутков и островов. Вы можете решить эту проблему с помощью оконных функций (доступно только в 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 минут, сумма увеличивается.

...