С LAG()
и LEAD()
оконными функциями и CTE
:
with cte as (
select t.*,
case when "msn" - lag("msn") over (partition by "num", "date" order by "msn") = 1 then 0 else 1 end isfrom,
case when lead("msn") over (partition by "num", "date" order by "msn") - "msn" = 1 then 0 else 1 end isto
from tablename t
)
select c1."num", c1."msn" rangefrom, min(c2."msn") rangeto, c1."date"
from cte c1 inner join cte c2
on c2."num" = c1."num" and c2."date" = c1."date"
and (
(c1.isfrom = 1 and c2.isto = 1 and c1."msn" < c2."msn")
or
(c1.isfrom = 1 and c1.isto = 1 and c1."msn" = c2."msn")
)
group by c1."num", c1."msn", c1."date"
order by c1."num", c1."msn", c1."date"
См. demo . Результаты:
> num | RANGEFROM | RANGETO | date
> :-- | --------: | ------: | :--------
> 1ab | 5 | 5 | 25/2/2019
> 1ab | 7 | 8 | 25/2/2019
> 1ac | 8 | 8 | 25/4/2019
> 1ad | 9 | 11 | 25/5/2019