У меня проблема с созданием правильного выражения SQL.

У меня есть таблица TICKET со столбцом TICKETID

TICKETID    
1000
1001

Затем у меня есть таблица STATUSHISTORY, откуда мне нужно узнать, что было в последний раз (максимальное время), когда этот билет входил в статус VENDOR (последний статус VENDOR) и когда он выходил из статуса VENDOR (выходя из статуса VENDOR, я имею в виду первый следующий статус INPROG, но только первый INPROG после статуса VENDOR, это всегда INPROG следующий статус после статуса VENDOR). Также возможно, что статус VENDOR для ID вообще не существует в STATUSHISOTRY (тогда должны быть возвращены значения NULL), но INPROG существует всегда - это может быть до, но также и после статуса VENDOR, если ID больше не находится в статусе VENDOR. Вот пример СТАТУШИСТОРИИ.

ID  TICKETID    STATUS    DATETIME
1   1000        INPROG    01.01.2017 10:00
2   1000        VENDOR    02.01.2017 10:00
3   1000        INPROG    03.01.2017 10:00
4   1000        VENDOR    04.01.2017 10:00
5   1000        INPROG    05.01.2017 10:00
6   1000        HOLD      06.01.2017 10:00
7   1000        INPROG    07.01.2017 10:00
8   1001        INPROG    02.02.2017 10:00
9   1001        VENDOR    03.02.2017 10:00
10  1001        INPROG    04.02.2017 10:00
11  1001        VENDOR    05.02.2017 10:00

Таким образом, результат при выполнении запроса из таблицы TICKET и выполнении JOIN с таблицей STATUSHISTORY должен быть:

ID     VENDOR_ENTERED      VENDOR_EXITED
1000   04.01.2017 10:00    05.01.2017 10:00
1001   05.02.2017 10:00    null

Потому что для ID 1000 последний статус VENDOR был в 04.01.2017, а статус первый INPROG после статуса VENDOR для этого ID был в 05.01.2017, а для ID 1001 последний Статус VENDOR был в 05.02.2017, и после этого статус INPROG еще не был. Если VENDOR не существует, тогда оба столбца должны быть нулевыми в результате. Я действительно застрял с этим, пробуя разные соединения, но без какого-либо прогресса. Спасибо заранее, если вы можете мне помочь.

-1
Veljko 28 Май 2017 в 11:31

2 ответа

Лучший ответ

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

Затем объедините записи, чтобы получить одну запись для каждой группы «вендоров». И используйте номера строк, чтобы получить самые последние записи. Так:

with vg as (
      select ticket,
             min(datetime) as vendor_entered,
             min(case when status = 'INPROG' then datetime end) as vendor_exitied
      from (select sh.*,
                   sum(case when status = 'VENDOR' then 1 else 0 end) over (partition by ticketid order by datetime) as grp
            from statushistory sh
           ) sh
      group by ticket, grp
     )
select vg.tiketid, vg.vendor_entered, vg.vendor_exited
from (select vg.*,
             row_number() over (partition by ticket order by vendor_entered desc) as seqnum
      from vg
     ) vg
where seqnum = 1;
1
Gordon Linoff 28 Май 2017 в 11:47

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

select  a.TicketID,
        a.VENDOR_ENTERED,
        min( EXIT_TIME ) as VENDOR_EXITED
from    (
          select  TicketID,
                  max( DATETIME ) as VENDOR_ENTERED
          from    StatusHistory
          where   Status = 'VENDOR'
          group by TicketID
        ) as a
        left join
        (
          select  TicketID,
                  DATETIME as EXIT_TIME
          from    StatusHistory
          where   Status = 'INPROG'
        ) as b
        on a.TicketID = b.TicketID
        and EXIT_TIME >= a.VENDOR_ENTERED
group by a.TicketID,
        a.VENDOR_ENTERED

DB2 не поддерживается в SQLfiddle, но стандартный пример SQL можно найти здесь.

0
Alex 28 Май 2017 в 09:21