Вот один из способов сделать это. Это не самый элегантный или эффективный способ, но это самый элементарный способ, который я мог придумать (за исключением действительно неэффективных вещей, таких как коррелированные подзапросы, которые нельзя легко раскрутить до соединений).
В первом подзапросе с псевдонимами a
я создаю все необходимые даты. Во втором подзапросе, b
, я создаю диапазоны дат, для которых нам нужно будет повторять определенные строки (в тестовых данных я допускаю переменное количество строк, которые должны повторяться, чтобы сделать одну из тонкостей проблема более очевидна).
Имея их в руках, легко получить результат, объединив эти два подзапроса и исходные данные. Увы, этот подход требует трехкратного чтения базовой таблицы; надеюсь, у вас не слишком много данных для обработки.
with
inputs ( dt, val1, val2 ) as (
select date '2017-08-14', 'x', 1 from dual union all
select date '2017-08-14', 'x', 2 from dual union all
select date '2017-08-17', 'y', 4 from dual union all
select date '2017-08-17', 'x', 3 from dual union all
select date '2017-08-19', 'a', 5 from dual
)
-- End of simulated inputs (for testing purposes only, not part of the solution).
-- Use your actual table and column names in the SQL query below.
select a.dt, i.val1, i.val2
from (
select min_dt + level - 1 as dt
from ( select min(dt) as min_dt from inputs )
connect by level <= sysdate - min_dt
) a
join
(
select dt, lead(dt, 1, sysdate) over (order by dt) as lead_dt
from (select distinct dt from inputs)
) b
on a.dt >= b.dt and a.dt < b.lead_dt
join
inputs i on i.dt = b.dt
order by dt, val1, val2
;
Вывод:
DT VAL1 VAL2
---------- ---- ----
2017-08-14 x 1
2017-08-14 x 2
2017-08-15 x 1
2017-08-15 x 2
2017-08-16 x 1
2017-08-16 x 2
2017-08-17 x 3
2017-08-17 y 4
2017-08-18 x 3
2017-08-18 y 4
2017-08-19 a 5
2017-08-20 a 5
person
mathguy
schedule
21.08.2017