Here is one way to do this. It assumes the dates are all pure dates (no time of day component - which in fact means the time of day is 00:00:00 everywhere). It also assumes you want the output to include all the dates between the first and the last date in the inputs.
The first and last dates are computed in the innermost query. Then all the dates between them are created with a hierarchical (connect by) query, and the result is left-joined to the original data. The output is then obtained by using the analytical last_value()
function with the ignore nulls
option.
with
inputs ( dt, value ) as (
select to_date('8/1/2017', 'mm/dd/yyyy'), 'x' from dual union all
select to_date('8/5/2017', 'mm/dd/yyyy'), 'b' from dual union all
select to_date('8/7/2017', 'mm/dd/yyyy'), 'a' from dual
)
-- End of simulated input data (for testing purposes only, not part of the solution).
-- Use your actual table and column names in the SQL query that begins below this line.
select dt, last_value(value ignore nulls) over (order by dt) as value
from ( select f.dt, i.value
from ( select min_dt + level - 1 as dt
from ( select max(dt) as max_dt, min(dt) as min_dt
from inputs
)
connect by level <= max_dt - min_dt + 1
) f
left outer join inputs i on f.dt = i.dt
)
;
DT VALUE
---------- -----
2017-08-01 x
2017-08-02 x
2017-08-03 x
2017-08-04 x
2017-08-05 b
2017-08-06 b
2017-08-07 a