多行/单列的开始/结束日期

时间:2019-06-21 14:55:20

标签: sql oracle12c

我需要根据每种状态的开始时间和结束时间(即特定状态何时开始以及该状态何时结束)创建从/到日期的输出。记录ID为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 :(得分:0)

最简单的方法是使用内置的“窗口功能” 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在当前组(或Window)中当前行的前面,如果没有这样的行,我们将返回{{1 }}

SYSDATE

此部分定义组(窗口)。 LEAD功能仅在组内起作用。在我们的例子中,定义组的是OVER(PARTITION BY mt.PARENT_ID ORDER BY mt.ID) 。不同的PARENT_ID,不同的组,因此您在PARENT_ID的一行上运行的LEAD无法找到PARENT_ID = 123的值。您还可以按多个字段进行分区,只需将其用逗号分隔即可。窗口将是行集,其中所有这些字段在整个行中都一致。当我们从“下一行”中查找日期时,重要的是在窗口中正确排列行,否则向前看1行可能无法满足您的期望。这就是PARENT_ID <> 123进入的地方。