Этот запрос с использованием аналитики c lead()
выполняет свою работу. Столбец note
показывает, происходит ли строка из ваших данных или отсутствует пробел:
select id, d1, d2, case dir when 3 then 'GAP' end note
from (
select id,
case when dir = 2
and lead(dir) over (partition by id order by dt) = 1
and lead(dt) over (partition by id order by dt) <> dt + 1
then dt + 1
else dt
end d1,
case when dir = 2
and lead(dir) over (partition by id order by dt) = 1
and lead(dt) over (partition by id order by dt) <> dt + 1
then 3
else dir
end dir,
case when lead(dir) over (partition by id order by dt) = 1
then lead(dt) over (partition by id order by dt) - 1
else lead(dt) over (partition by id order by dt)
end d2
from (
select * from a unpivot (dt for dir in (validfrom as 1, validto as 2)) union
select * from b unpivot (dt for dir in (validfrom as 1, validto as 2)) ) )
where dir in (1, 3)
dbfiddle demo
Сначала данные не сворачиваются, чтобы все даты были в одном столбце, это проще для дальнейшей аналитики. Union удаляет повторяющиеся значения. В столбце dir
указывается дата: from
или to
. Тогда применяется lead
логи c, в зависимости от типа этого направления. Думаю, это можно несколько упростить :)