Каков наилучший способ в SQL объединить последовательные события, основанные на сопоставлении времени окончания и времени начала? - PullRequest
1 голос
/ 06 февраля 2020

Эта база данных, в которой я работаю, записывает события на основе идентификатора детали и времени, в которое она активна. Проблема, с которой я столкнулся, заключается в том, что эти события усекаются в течение одного дня. Если активное время для детали переносится на следующий день, событие будет разделено на количество дней, к которым оно относится. В этом случае активная временная метка начала следующего дня совпадает с активной конечной меткой времени предыдущего. Я пытаюсь найти способ объединить эти разделенные события в одну запись с «истинным» временем начала и окончания, когда каждая часть активна.


Вот пример того, что набор данных выглядит следующим образом:

date    part_id   active_start  active_end
1/1/2019    100   1/1/19 8:00   1/1/19 9:30
1/1/2019    100   1/1/19 14:00  1/2/19 0:00
1/2/2019    100   1/2/19 0:00   1/3/19 0:00
1/3/2019    100   1/3/19 0:00   1/4/19 0:00
1/4/2019    100   1/4/19 0:00   1/4/19 8:00
1/7/2019    100   1/7/19 6:00   1/8/19 0:00
1/8/2019    100   1/8/19 0:00   1/9/19 0:00
1/9/2019    100   1/9/19 0:00   1/9/19 11:30
1/11/2019   100   1/11/19 12:00 1/11/19 22:00
1/13/2019   100   1/13/19 14:30 1/14/19 0:00
1/14/2019   100   1/14/19 0:00  1/15/19 0:00
1/15/2019   100   1/15/19 0:00  1/15/19 8:30

Я пытаюсь сократить его до следующего:

date    part_id   active_start    active_end
1/1/2019    100   1/1/19 8:00     1/1/19 9:30
1/1/2019    100   1/1/19 14:00    1/4/19 8:00
1/7/2019    100   1/7/19 6:00     1/9/19 11:30
1/11/2019   100   1/11/19 12:00   1/11/19 22:00
1/13/2019   100   1/13/19 14:30   1/15/19 8:30

Имеется ~ 70 различных номеров деталей, в каждом из которых может быть до 200 различных активных событий. за период наблюдения. Активные события могут длиться до нескольких дней. Поскольку в * 1011 я довольно неопытен, любая помощь будет принята с благодарностью.

1 Ответ

1 голос
/ 06 февраля 2020

Это проблема пробелов и островов, когда вы хотите сгруппировать смежные строки.

Вот одно решение, использующее оконные функции:

select 
    min(date) date,
    part_id,
    min(active_start) active_start,
    max(active_end) active_end
from (
    select
        t.*,
        sum(case when lag_active_end = active_start then 0 else 1 end)
            over(partition by part_id order by active_start) grp
    from (
        select 
            t.*, 
            lag(active_end) over(partition by part_id order by active_start) lag_active_end
        from mytable t
    ) t
) t
group by part_id, grp

Самый внутренний запрос извлекает дата окончания предыдущей записи с таким же значением part_id. Промежуточный запрос делает сумму окна, которая увеличивается на 1 каждый раз, когда предыдущая конечная дата не равна текущей начальной дате: это определяет группы смежных строк. Наконец, внешний запрос агрегирует по группам и вычисляет начало и конец диапазона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...