© 2019 Rank & State Algorithm by Jörg & Christine Schmidt. Just for trying out. No warranty.
create view product_2 as with product as ( select *, row_number() over (partition by product_id order by registered_from) as rankReg, row_number() over (partition by product_id order by valid_from, registered_from) as rankVal from product_1 ), productExt as ( select product_id, rankReg, rankVal from product union select product_id, 0, 0 from product where rankReg = 1 ), tbl as ( select b.product_id, b.rankReg, b.rankVal,
a.rankVal as rankValPre from productExt a join productExt b
on a.product_id = b.product_id and a.rankReg + 1 = b.rankReg ), head as ( select a.product_id, a.rankReg, b.rankVal,
a.rankReg - 1 as state, row_number() over(partition by a.product_id, b.rankVal order by a.rankReg) as rankRegrank from tbl a join productExt b
on a.product_id = b.product_id and b.rankVal between a.rankValPre and a.rankVal - 1 ), tail as ( select a.product_id, a.rankReg as rankRegTo, b.rankVal, row_number() over(partition by a.product_id, b.rankVal order by a.rankReg) as rankRegTorank from tbl a join productExt b on a.product_id = b.product_id and b.rankVal between a.rankVal and a.rankValPre - 1 ), tbl2 as ( select a.product_id, a.state, a.rankReg, case when b.rankRegTo is null then 0 else b.rankRegTo end as rankRegTo, min(a.rankVal) as rankVal, max(a.rankVal) + 1 as rankValTo from head a left join tail b on a.product_id = b.product_id and a.state > 0 and a.rankVal = b.rankVal
and a.rankRegrank = b.rankRegTorank group by a.product_id, a.state, a.rankReg, b.rankRegTo union select product_id, rankReg as state, rankReg, rankReg + 1 as rankRegTo, rankVal, 0 as rankValTo from product ) select a.product_id, b.registered_from, case when c.registered_from is null then '9999-12-31' else c.registered_from end as registered_to, d.valid_from, case when e.valid_from is null then '9999-12-31' else e.valid_from end as valid_to, f.price from tbl2 a inner join product b on a.product_id = b.product_id and a.rankReg = b.rankReg left join product c on a.product_id = c.product_id and a.rankRegTo = c.rankReg inner join product d on a.product_id = d.product_id and a.rankVal = d.rankVal left join product e on a.product_id = e.product_id and a.rankValTo = e.rankVal inner join product f on a.product_id = f.product_id and a.state = f.rankReg;