Использование LEAD и LAG с неизвестным количеством строк - PullRequest
0 голосов
/ 03 апреля 2020

У меня есть таблица с информацией об участии в сервисе для группы людей, как в приведенном ниже коде, который я запускаю в Oracle.

CREATE TABLE SRVC_EPISODES
(
   CASE_INDEX        NUMBER (10),
   CLIENT_ID         NUMBER (10),
   SRVC_ID           NUMBER (10),
   SRVC_START_DT     DATE,
   SRVC_END_DT       DATE,
   SRVC_END_REASON   VARCHAR2 (70 BYTE)
);

INSERT INTO SRVC_EPISODES VALUES (1, 1, 3747, TO_DATE('03/28/2017', 'mm/dd/yyyy'), TO_DATE('06/27/2017', 'mm/dd/yyyy'), 'Full Completion');
INSERT INTO SRVC_EPISODES VALUES (2, 1, 5231, TO_DATE('02/16/2018', 'mm/dd/yyyy'), TO_DATE('06/30/2018', 'mm/dd/yyyy'), 'Service Transfer');
INSERT INTO SRVC_EPISODES VALUES (3, 1, 3929, TO_DATE('07/01/2018', 'mm/dd/yyyy'), TO_DATE('07/01/2018', 'mm/dd/yyyy'), 'Service Transfer');
INSERT INTO SRVC_EPISODES VALUES (4, 1, 6688, TO_DATE('07/13/2018', 'mm/dd/yyyy'), TO_DATE('10/19/2018', 'mm/dd/yyyy'), 'Full Completion');
INSERT INTO SRVC_EPISODES VALUES (5, 2, 73, TO_DATE('10/03/2017', 'mm/dd/yyyy'), TO_DATE('06/30/2018', 'mm/dd/yyyy'), 'Service Transfer');
INSERT INTO SRVC_EPISODES VALUES (6, 2, 201, TO_DATE('05/07/2018', 'mm/dd/yyyy'), TO_DATE('06/30/2018', 'mm/dd/yyyy'), 'Service Transfer');
INSERT INTO SRVC_EPISODES VALUES (7, 2, 8102, TO_DATE('06/02/2018', 'mm/dd/yyyy'), TO_DATE('06/30/2018', 'mm/dd/yyyy'), 'Service Transfer');
INSERT INTO SRVC_EPISODES VALUES (8, 2, 4164, TO_DATE('07/01/2018', 'mm/dd/yyyy'), TO_DATE('03/20/2019', 'mm/dd/yyyy'), 'Incomplete');
INSERT INTO SRVC_EPISODES VALUES (9, 2, 2066, TO_DATE('07/01/2018', 'mm/dd/yyyy'), TO_DATE('12/02/2019', 'mm/dd/yyyy'), 'Failed Classes');

Проблема, с которой я сталкиваюсь, заключается в том, что часто человек будет передавать провайдеров на полпути через их услуги, как указано различными SRVC_ID и предшествующими SRVC_END_REASON, при сортировке по CLIENT_ID -> SRVC_START_DT -> SRVC_END_DT.

В приведенном ниже примере CLIENT_ID # 1 имеет два разных эпизода обслуживания - один, который произошел с 28.03.2017 по 27.06.2017, который они успешно завершили. Однако их следующая услуга проходила с тремя разными провайдерами (три разных идентификатора услуги) и проходила с 16.02.2008 по 19.10.2008, которую они также успешно завершили.

CLIENT_ID # 4 также имеет два отдельных сервисных эпизода. Первый состоялся с 3.10.2017 и завершился 20.03.2009 с неполным. Их следующий сервисный эпизод проходил с 01.07.2008 по 02.12.2009, но они провалились. Несмотря на то, что это может быть трудно понять, CASE_INDEX # 9 - это другая служба, поскольку предыдущая служба не имела «передачу» в качестве причины завершения службы (сгруппирована по CLIENT_ID, затем отсортирована по SRVC_START_DT, затем SRVC_END_DT).

Я бы сказал, что самая большая проблема, с которой я сталкиваюсь, заключается в том, что количество переводов для каждого клиента не является фиксированным, если они вообще имеют какие-либо переводы. Если нам нужно, давайте предположим, что максимальное количество передач будет 5.

Я знаю, что решение этого заключается в использовании опережения / отставания, но я после большой борьбы не могу понять, как. Моя конечная цель - иметь правильные SRVC_START_DT, SRVC_END_DT и SRVC_END_REASON, как в примере ниже.

Data Example

Ответы [ 2 ]

3 голосов
/ 03 апреля 2020

Это, кажется, делает это (наряду с парой дополнительных столбцов, с которыми можно обойтись):

select v2.*
,      min(srvc_start_dt) over (partition by grp order by srvc_start_dt) new_start_dt
,      max(srvc_end_dt)    over (partition by grp order by srvc_start_dt desc) new_end_dt
,      first_value(srvc_end_reason) over (partition by grp order by srvc_start_dt desc) new_end_reason
from (
  select v.*
  ,     sum(stat) over(order by client_id desc, srvc_start_dt desc, srvc_end_dt desc) grp 
  from (
    select s.*
    ,      case when srvc_end_reason not like '%Transfer%' then 1 end as stat
    from   SRVC_EPISODES s
  ) v
) v2
order by 1;
2 голосов
/ 03 апреля 2020

Отчасти для моего собственного развлечения и любопытства / обучения, вы также можете сделать это с match_recognize (12c +):

select case_index, client_id, srvc_id, srvc_start_dt, srvc_end_dt, srvc_end_reason,
  new_start_dt, new_end_dt, new_end_reason
from srvc_episodes
match_recognize (
  partition by client_id
  order by srvc_start_dt, srvc_end_dt
  measures
    first(srvc_start_dt) as new_start_dt,
    final last(srvc_end_dt) as new_end_dt,
    final last(srvc_end_reason) as new_end_reason
  all rows per match
  after match skip past last row
  pattern (complete | transfer+ complete)
  define
    transfer as transfer.srvc_end_reason = 'Service Transfer',
    complete as complete.srvc_end_reason != 'Service Transfer'
)
order by case_index;

CASE_INDEX  CLIENT_ID    SRVC_ID SRVC_START SRVC_END_D SRVC_END_REASON      NEW_START_ NEW_END_DT NEW_END_REASON      
---------- ---------- ---------- ---------- ---------- -------------------- ---------- ---------- --------------------
         1          1       3747 2017-03-28 2017-06-27 Full Completion      2017-03-28 2017-06-27 Full Completion     
         2          1       5231 2018-02-16 2018-06-30 Service Transfer     2018-02-16 2018-10-19 Full Completion     
         3          1       3929 2018-07-01 2018-07-01 Service Transfer     2018-02-16 2018-10-19 Full Completion     
         4          1       6688 2018-07-13 2018-10-19 Full Completion      2018-02-16 2018-10-19 Full Completion     
         5          2         73 2017-10-03 2018-06-30 Service Transfer     2017-10-03 2019-03-20 Incomplete          
         6          2        201 2018-05-07 2018-06-30 Service Transfer     2017-10-03 2019-03-20 Incomplete          
         7          2       8102 2018-06-02 2018-06-30 Service Transfer     2017-10-03 2019-03-20 Incomplete          
         8          2       4164 2018-07-01 2019-03-20 Incomplete           2017-10-03 2019-03-20 Incomplete          
         9          2       2066 2018-07-01 2019-12-02 Failed Classes       2018-07-01 2019-12-02 Failed Classes      

db <> fiddle

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