Oracle SQL - 填充缺失日期并填充给定ID的最后可用日期值

时间:2018-03-28 10:59:05

标签: sql oracle oracle11g

当前数据集

enter image description here

预期结果 - 寻找oracle SQL脚本,它将帮助我填充缺少的日期并携带/滚动/复制给定ID的ID和值。

enter image description here

`
当前数据集 - 具有日期,ID和值

Date    | ID | Value
--------------------
2/4/17  | 3  |  4.4
2/4/17  | 9  |  6.2
2/9/17  | 3  |  4.7
2/9/17  | 4  |  7.4
2/9/17  | 9  |  9.4
2/11/17 | 3  |  9.7
2/11/17 | 7  |  12.4

`预期结果 - 寻找oracle SQL脚本,它将帮助我填充缺少的日期并携带/滚动/复制给定ID的ID和值。

Expected Result

Date    | ID | Value
--------------------
2/4/17  | 3  |  4.4
2/4/17  | 9  |  6.2
2/5/17  | 3  |  4.4
2/5/17  | 9  |  6.2
2/6/17  | 3  |  4.4
2/6/17  | 9  |  6.2
2/7/17  | 3  |  4.4
2/7/17  | 9  |  6.2
2/8/17  | 3  |  4.4
2/8/17  | 9  |  6.2
2/9/17  | 3  |  4.7
2/9/17  | 4  |  7.4
2/9/17  | 9  |  9.4
2/10/17 | 3  |  4.7
2/10/17 | 4  |  7.4
2/10/17 | 9  |  9.4
2/11/17 | 3  |  9.7
2/11/17 | 7  |  12.4

1 个答案:

答案 0 :(得分:2)

create table test_roll
( dte date,
  id int,
  value number(9,2)
  );

insert into test_roll values(to_date('2/4/17','MM/DD/YYYY'),3, 4.4);
insert into test_roll values(to_date('2/4/17','MM/DD/YYYY'),9, 6.2);
insert into test_roll values(to_date('2/9/17','MM/DD/YYYY'),3, 4.7);
insert into test_roll values(to_date('2/9/17','MM/DD/YYYY'),4, 7.4);
insert into test_roll values(to_date('2/9/17','MM/DD/YYYY'),9, 9.4);
insert into test_roll values(to_date('2/11/17','MM/DD/YYYY'),3, 9.7);
insert into test_roll values(to_date('2/11/17','MM/DD/YYYY'),7, 12.4);

commit;

select * from test_roll order by dte, id;

DTE               ID      VALUE
--------- ---------- ----------
04-FEB-17          3        4.4
04-FEB-17          9        6.2
09-FEB-17          3        4.7
09-FEB-17          4        7.4
09-FEB-17          9        9.4
11-FEB-17          3        9.7
11-FEB-17          7       12.4

SELECT DTE, ID, LAST_VALUE(value) IGNORE NULLS OVER (PARTITION BY ID ORDER BY ID,DTE) AS value
   FROM (
        WITH DATES AS
        (
            select DISTINCT ID, (MIN_DTE + LEVEL - 1) REAL_DTE
            FROM (
                  select ID, min(DTE) as MIN_DTE, 
                    greatest( max(dte), (select max(dte) - 1 from test_roll)) as MAX_DTE
                    FROM test_roll
                  group by ID )
            CONNECT BY LEVEL <= MAX_DTE - MIN_DTE + 1 
        )
        SELECT D.REAL_DTE AS DTE,
               D.ID as ID,
               t.value as value
      FROM DATES D
            LEFT JOIN test_roll t ON t.ID=D.ID AND D.REAL_DTE=t.DTE
       ) ROLLED
       ORDER BY DTE, ID;

DTE               ID      VALUE
--------- ---------- ----------
04-FEB-17          3        4.4
04-FEB-17          9        6.2
05-FEB-17          3        4.4
05-FEB-17          9        6.2
06-FEB-17          3        4.4
06-FEB-17          9        6.2
07-FEB-17          3        4.4
07-FEB-17          9        6.2
08-FEB-17          3        4.4
08-FEB-17          9        6.2
09-FEB-17          3        4.7
09-FEB-17          4        7.4
09-FEB-17          9        9.4
10-FEB-17          3        4.7
10-FEB-17          4        7.4
10-FEB-17          9        9.4
11-FEB-17          3        9.7
11-FEB-17          7       12.4