Вы можете использовать рекурсивный CTE, который является стандартом SQL. Например, CTE expanded
в следующем запросе работает как в Oracle, так и в Postgres (весь запрос работает только в Oracle, будет работать в Postgres после удаления from dual
и добавления with recursive
):
with original as (
select 1 as id, date '2019-03-01' as start_date, date '2019-03-07' as end_date, 'text1' as field from dual
union
select 2 as id, date '2019-04-10' as start_date, date '2019-04-15' as end_date, 'text2' as field from dual
), expanded (id, the_date, end_date, field) as (
select id, start_date, end_date, field
from original
union all
select original.id, expanded.the_date + 1, original.end_date, original.field
from expanded
join original on expanded.id = original.id and expanded.the_date + 1 <= original.end_date
)
select id, the_date, field
from expanded
order by id, the_date
См. https://dbfiddle.uk/?rdbms=oracle_18&fiddle=c0e49c2fff9e24fee8401e8ac9a16ceb
Примечание: из-за арифметической ошибки датировки Oracle CTE запрос не будет работать в Oracle до 11.2 (вы получаете ошибку ORA-01841: (full) year must be between -4713 and +9999, and not be 0
, поскольку даты ошибочно идут вниз). Если у вас более старая версия Oracle, вам, вероятно, лучше использовать connect by, так как использование CTE требует некоторого обходного пути для ошибки (обратное направление или предварительно вычисленные последовательности), что тоже сложно. Для более новой версии Oracle (или других поставщиков - если кто-то найдет этот вопрос) я рекомендую предпочесть стандарт SQL.