Расчет времени с указанием даты и времени по группам - PullRequest
0 голосов
/ 15 апреля 2020

У меня есть две таблицы Билеты и Задачи. Когда билет зарегистрирован, он появляется в таблице «Билеты», и каждое действие, выполненное с этим билетом, сохраняется в таблице «Задачи». Таблица заявок включает информацию о том, кто создал заявку, даты начала и окончания (если она закрыта) и т. Д. c. Таблица задач выглядит следующим образом:

ID  Ticket_ID   Task_type_ID    Task_type   Group_ID    Submit_Date
1   120         1               Opened      3           2016-12-09 11:10:22.000
2   120         2               Assign      4           2016-12-09 12:10:22.000
3   120         3               Paused      4           2016-12-09 12:30:22.000
4   120         4               Unpause     4           2016-12-10 10:30:22.000
5   120         2               Assign      6           2016-12-12 10:30:22.000
6   120         2               Assign      7           2016-12-12 15:30:22.000
7   120         5               Modify      NULL        2016-12-13 15:30:22.000
8   120         6               Closed      NULL        2016-12-13 16:30:22.000

Я бы хотел посчитать, сколько времени каждая группа выполнила свою задачу. Время начала - это время, когда билет был назначен определенной группе, а время окончания - когда эта группа завершает свою задачу (если они назначают ее в другом месте или закрывают). Но это не должно включать приостановленное время (task_type_ID 3 до 4). Также, когда заявка назначается другой группе, новый идентификатор группы появляется в предыдущем задании / строке. Если задача проходит через несколько групп, она должна рассчитать, сколько времени билет находился в руках каждой группы. Я знаю, что это сложно, но, возможно, у кого-то есть идея, из которой я могу начать строить.

Ответы [ 2 ]

1 голос
/ 15 апреля 2020

Я на самом деле думаю, что это довольно просто. Просто используйте lead(), чтобы получить значение времени следующей отправки и агрегировать по тикету и группе, игнорируя паузы:

select ticket_id, group_id, sum(dur_sec)
from (select t.*,
             datediff(second, submit_date, lead(submit_date) over (partition by ticket_id order by submit_date)) as dur_sec
      from mytable t
     ) t
where task_type <> 'Paused' and group_id is not null
group by ticket_id, group_id;

Здесь - это скрипта db <> (с благодарностью GMB за создание оригинальной скрипки).

1 голос
/ 15 апреля 2020

Это довольно сложная проблема пробелов и островков.

Вот один из подходов:

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