Хммм. Я интерпретирую это как проблему разрыва и островков с некоторыми поворотами. Вместо того, чтобы помещать «конечные» значения в разные строки, я бы поместил эффективные и конечные даты в одну строку:
select product, store, region, type,
min(eff_dt),
date_add(lead(eff_dt) over (partition by product order by min(eff_dt), -1) as
from (select t.*,
row_number() over (partition by product order by eff_dt) as seqnum_p,
row_number() over (partition by product, store, region, type order by eff_dt) as seqnum_psrt
from t
) t
group by product, store, region, type, (seqnum - seqnum_psrt);
Если вы хотите это в разных строках, вы можете использовать union all
:
select product, store, region, type, eff_dt
from (select t.*,
lag(eff_dt) over (partition by product, store, region, type order by eff_dt) as prev_psrt_date,
lag(eff_dt) over (partition by product order by eff_dt) as prev_date
from t
) t
where prev_date is null or prev_date <> prev_psrt_date
union all
select product, store, region, type,
date_add(next_date, 1)
from (select t.*,
lead(eff_dt) over (partition by product, store, region, type order by eff_dt) as next_psrt_date,
lead(eff_dt) over (partition by product order by eff_dt) as next_date
from t
) t
where next_date <> next_psrt_date or next_psrt_date is null;
Хитрость при поиске строк с одинаковыми значениями заключается в сравнении предыдущей / следующей даты - но по разным разделам данных. Это проще, чем сравнивать каждый столбец независимо, и это также работает для NULL
значений.