Это проблема промежутков и островов. Вот один из подходов, который использует lag()
и кумулятивное sum()
для определения групп последовательных перекрывающихся строк, которые затем можно агрегировать:
select
userRegistryID,
min(rn2) min_rn2,
max(rn2) max_rn2,
min(loginTime) minLoginTime,
max(logoutTime) maxLogoutTime,
count(*) no_records
from (
select
t.*,
sum(case when loginTime <= lagLogoutTime then 0 else 1 end)
over(partition by userRegistryID order by rn2) grp
from (
select
t.*,
lag(logoutTime) over(partition by userRegistryID order by rn2) lagLogoutTime
from mytable t
) t
) t
group by userRegistryID, grp
order by userRegistryID, minLoginTime
В качестве альтернативы, если вы не хотите агрегировать строки но вместо этого добавьте даты начала и окончания каждого сеанса в каждую строку, вы можете сделать:
select
rn2,
userRegistryID,
loginTime,
logoutTime,
min(loginTime) over(partition by userRegistryID, grp) finalLoginTime,
max(logoutTime) over(partition by userRegistryID, grp) finalLogoutTime
from (
select
t.*,
sum(case when loginTime <= lagLogoutTime then 0 else 1 end)
over(partition by userRegistryID order by rn2) grp
from (
select
t.*,
lag(logoutTime) over(partition by userRegistryID order by rn2) lagLogoutTime
from mytable t
) t
) t
order by userRegistryID, rn2