Получение даты начала / окончания из нескольких строк / одного столбца - PullRequest
0 голосов
/ 21 июня 2019

Мне нужно создать выходные данные с / до дат, основанных на времени начала и времени окончания для каждого статуса, другими словами, когда начался определенный статус и когда этот статус закончился, например, для записи с идентификатором 2 Обработка началась 01/04/2019 и закончилась 01/05/2019, когда был добавлен следующий статус.

Вот пример сценария:

CREATE TABLE mytable (ID NUMBER, PARENT_ID NUMBER, STATUS VARCHAR2(20), ADDED_DATE DATE);  
INSERT INTO MYTABLE (ID, PARENT_ID, STATUS, ADDED_DATE) VALUES
(1, 123, 'Requested', TO_DATE('01/01/2019', 'MM/DD/YYYY'));  
INSERT INTO MYTABLE (ID, PARENT_ID, STATUS, ADDED_DATE) VALUES
(2, 123, 'Processing', TO_DATE('01/04/2019', 'MM/DD/YYYY'));
INSERT INTO MYTABLE (ID, PARENT_ID, STATUS, ADDED_DATE) VALUES
(3, 123, 'Approved', TO_DATE('01/05/2019', 'MM/DD/YYYY'));  
INSERT INTO MYTABLE (ID, PARENT_ID, STATUS, ADDED_DATE) VALUES
(4, 567, 'Requested', TO_DATE('03/12/2019', 'MM/DD/YYYY'));  
INSERT INTO MYTABLE (ID, PARENT_ID, STATUS, ADDED_DATE) VALUES
(5, 567, 'Processing', TO_DATE('03/13/2019', 'MM/DD/YYYY'));  
INSERT INTO MYTABLE (ID, PARENT_ID, STATUS, ADDED_DATE) VALUES
(6, 4547, 'Requested', TO_DATE('04/22/2019', 'MM/DD/YYYY'));  
INSERT INTO MYTABLE (ID, PARENT_ID, STATUS, ADDED_DATE) VALUES
(7, 4547, 'Processing', TO_DATE('04/24/2019', 'MM/DD/YYYY'));  
INSERT INTO MYTABLE (ID, PARENT_ID, STATUS, ADDED_DATE) VALUES
(8, 4547, 'On-hold', TO_DATE('04/27/2019', 'MM/DD/YYYY'));  
INSERT INTO MYTABLE (ID, PARENT_ID, STATUS, ADDED_DATE) VALUES
(9, 4547, 'Denied', TO_DATE('05/05/2019', 'MM/DD/YYYY'));  
INSERT INTO MYTABLE (ID, PARENT_ID, STATUS, ADDED_DATE) VALUES
(10, 15, 'Requested', TO_DATE('03/16/2019', 'MM/DD/YYYY')); 

Желаемый вывод:

ID    PARENT_ID     STATUS        FROM_DT        TO_DT  
1     123           Requested     01/01/2019     01/04/2019  
2     123           Processing    01/04/2019     01/05/2019  
3     123           Approved      01/05/2019     SYSDATE  
4     567           Requested     03/12/2019     03/13/2019  
5     567           Processing    03/13/2019     SYSDATE  
6     4547          Requested     04/22/2019     04/24/2019  
7     4547          Processing    04/24/2019     04/27/2019  
8     4547          On-hold       04/27/2019     05/05/2019  
9     4547          Denied        05/05/2019     SYSDATE  
10    15            Requested     03/16/2019     SYSDATE  

1 Ответ

0 голосов
/ 21 июня 2019

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

SELECT 
  mt.ID,
  mt.PARENT_ID,
  mt.STATUS,
  mt.ADDED_DATE as FROM_DT,
  LEAD(mt.ADDED_DATE, 1, SYSDATE ) OVER (PARTITION BY mt.PARENT_ID ORDER BY mt.ID) as TO_DT
FROM
  mytable mt
ORDER BY
  mt.ID

Тот же результат может быть достигнут другими способами, но это наиболее эффективно.Чтобы объяснить синтаксис для LEAD:

LEAD(mt.ADDED_DATE, 1, SYSDATE)

Мы получаем значение ADDED_DATE, 1 на строку впереди текущей строки в текущей группе (или окне), и если естьнет такой строки мы возвращаем SYSDATE

OVER(PARTITION BY mt.PARENT_ID ORDER BY mt.ID)

Эта часть определяет группу (Window).Функция LEAD работает только внутри группы.В нашем случае, что определяет группу, это PARENT_ID.Разные PARENT_ID, разные группы, поэтому вы LEAD, работающие в строке для PARENT_ID = 123, не можете найти значение для PARENT_ID <> 123.Вы также можете разделить на несколько полей, просто разделите их запятыми.Окно будет набором строк, где все эти поля совпадают по набору.Поскольку мы ищем дату из «следующей строки», важно, чтобы строки в окне были упорядочены правильно, в противном случае просмотр 1 строки вперед может не дать того, что вы ожидаете.Вот тут и приходит ORDER BY.

...