Разбить поток событий на сессии по 30-минутному разрыву неактивности
Таблица events(user_id, event_time) — сырой поток событий. Сессия заканчивается, когда пользователь неактивен более 30 минут; следующее событие начинает новую сессию. Верните число сессий на пользователя.
-- сессии на пользователя, разрыв по неактивности >30 минут
Напишите запрос.
На пользователя берут LAG(event_time) с сортировкой по времени. Помечают новую сессию, когда разрыв до предыдущего события больше 30 минут или предыдущего события нет (LAG равен NULL). Сумма этих флагов старта на пользователя и есть число сессий.
- ✗Делить весь активный интервал на 30 минут вместо анализа разрывов
- ✗Бить на окна по часам, а не по разрыву между событиями
- ✗Считать близкие события как сессии, а не считать старты сессий
- →Как присвоить каждому отдельному событию id сессии?
- →Как первое событие пользователя не теряется как старт сессии?
Look back one event per user with LAG, mark a session start whenever the gap exceeds the timeout (or there is no prior event), then sum the starts:
WITH gaps AS (
SELECT user_id,
event_time,
CASE
WHEN event_time - LAG(event_time) OVER (PARTITION BY user_id ORDER BY event_time)
> INTERVAL '30 minutes'
OR LAG(event_time) OVER (PARTITION BY user_id ORDER BY event_time) IS NULL
THEN 1 ELSE 0
END AS is_session_start
FROM events
)
SELECT user_id, SUM(is_session_start) AS session_count
FROM gaps
GROUP BY user_id;
The gap is between consecutive events, not against a fixed clock grid: two events 25 minutes apart stay in one session even if they straddle a half-hour boundary. The first event per user has a NULL LAG, so it must be forced to start a session, otherwise every user would be undercounted by one. To label each event with a running session number, replace the sum with a SUM(is_session_start) OVER (PARTITION BY user_id ORDER BY event_time).