I tried to use running count distinct user+session
with mydata as(--test data, use your table instead of this CTE
select 's1' session_id,'u1' user_id,'2021-01-01 0:00:00' session_time union all
select 's1','u1','2021-01-01 0:00:01' union all
select 's1','u1','2021-01-01 0:00:02' union all
select 's1','u1','2021-01-01 0:00:03' union all
select 's1','u2','2021-01-01 0:00:04' union all
select 's1','u2','2021-01-01 0:00:05' union all
select 's1','u2','2021-01-01 0:00:06' union all
select 's1','u2','2021-01-01 0:00:07' union all
select 's1','u1','2021-01-01 0:00:08' union all
select 's1','u1','2021-01-01 0:00:09' union all
select 's1','u1','2021-01-01 0:00:10' union all
select 's1','u1','2021-01-01 0:00:11')
select session_id, user_id, min(session_time) session_start_time, max(session_time)session_end_time
from
(
select session_id, user_id, session_time,
count(distinct session_id, user_id) over (order by session_time) cnt_user_session
from mydata
)s group by session_id, user_id, cnt_user_session
order by session_start_time
Result:
session_id user_id session_start_time session_end_time
s1 u1 2021-01-01 0:00:00 2021-01-01 0:00:03
s1 u2 2021-01-01 0:00:04 2021-01-01 0:00:07
s1 u1 2021-01-01 0:00:08 2021-01-01 0:00:11
It will not wok if the same user repeats again: adding more u2 s1 records will produce the same running count and it will not work, so, the LEAD or LAG is necessary.
Using LAG we can calculate flag when session changes and use running sum of flags to calculate new_session_id (to be used for grouping):
with mydata as(
select 's1' session_id,'u1' user_id,'2021-01-01 0:00:00' session_time union all
select 's1','u1','2021-01-01 0:00:01' union all
select 's1','u1','2021-01-01 0:00:02' union all
select 's1','u1','2021-01-01 0:00:03' union all
select 's1','u2','2021-01-01 0:00:04' union all
select 's1','u2','2021-01-01 0:00:05' union all
select 's1','u2','2021-01-01 0:00:06' union all
select 's1','u2','2021-01-01 0:00:07' union all
select 's1','u1','2021-01-01 0:00:08' union all
select 's1','u1','2021-01-01 0:00:09' union all
select 's1','u1','2021-01-01 0:00:10' union all
select 's1','u1','2021-01-01 0:00:11' union all
select 's1','u2','2021-01-01 0:00:12' --added this record
)
select session_id, user_id, min(session_time) session_start_time, max(session_time)session_end_time
from
(
select session_id, user_id, session_time,
sum(changed_flag) over (order by session_time) new_session_id
from
(
select session_id, user_id, session_time,
case when concat(session_id,'_', user_id) <>
lag(concat(session_id,'_', user_id)) over (order by session_time)
then 1
else 0
end changed_flag
from mydata
)s
) s
group by new_session_id, user_id, session_id
order by session_start_time
Result:
session_id user_id session_start_time session_end_time
s1 u1 2021-01-01 0:00:00 2021-01-01 0:00:03
s1 u2 2021-01-01 0:00:04 2021-01-01 0:00:07
s1 u1 2021-01-01 0:00:08 2021-01-01 0:00:11
s1 u2 2021-01-01 0:00:12 2021-01-01 0:00:12