Это довольно сложная проблема пробелов и островков.
Вот один из подходов:
select distinct
ticket_id,
group_id,
sum(sum(datediff(minute, submit_date, lead_submit_date)))
over(partition by group_id) elapsed_minutes
from (
select
t.*,
row_number() over(partition by ticket_id order by submit_date) rn1,
row_number() over(partition by ticket_id, group_id order by submit_date) rn2,
lead(submit_date) over(partition by ticket_id order by submit_date) lead_submit_date
from mytable t
) t
where task_type <> 'Paused' and group_id is not null
group by ticket_id, group_id, rn1 - rn2
В подзапросе мы присваиваем номера строк записям в двух разных разделы (по тикетам или по группам и ) и восстановить дату следующей записи с lead()
.
Затем мы можем использовать разницу между номерами строк для построения групп «смежных» записей (где заявки остаются в одной группе), не принимая во внимание периоды, когда заявка была приостановлена. Агрегация вступает в игру.
Последний шаг - вычисление общего времени, проведенного в каждой группе: это обрабатывает случай, когда заявка назначается одной и той же группе более одного раза в течение ее жизненного цикла (хотя это не показывает в вашем примере данных описание вопроса звучит так, как будто это может произойти). Мы могли бы сделать это с другим уровнем агрегации, но я выбрал сумму окна и distinct
, что позволяет избежать добавления еще одного уровня вложенности в запрос.
Независимое выполнение подзапроса может помочь в понимании логики c лучше (см. приведенную ниже дб скрипку).
Для ваших примеров данных запрос дает :
ticket_id | group_id | minutes_elapsed
--------: | -------: | --------------:
120 | 3 | 60
120 | 4 | 2900
120 | 6 | 300
120 | 7 | 1440