Как посчитать Sessions в SQL
orders поле promo_code может быть NULL. Что произойдёт со строкой, где promo_code = NULL, при фильтре WHERE promo_code <> 'NONE'?Содержание:
Зачем Sessions
DAU считают активных за день, но один пользователь может зайти 10 раз и закрыть. Это не вовлечённость — это сломанный онбординг. Сессии показывают, сколько отдельных «визитов» делает пользователь.
Что такое Session
Session — последовательность событий одного пользователя без пауз длиннее session_timeout (обычно 30 минут).
Sessionization через SQL
Данные: events(user_id, event_time).
WITH events_with_gap AS (
SELECT
user_id,
event_time,
LAG(event_time) OVER (PARTITION BY user_id ORDER BY event_time) AS prev_event,
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_new_session
FROM events
),
sessions AS (
SELECT
user_id,
event_time,
SUM(is_new_session) OVER (PARTITION BY user_id ORDER BY event_time) AS session_num
FROM events_with_gap
)
SELECT
user_id,
session_num,
MIN(event_time) AS session_start,
MAX(event_time) AS session_end,
COUNT(*) AS events_count,
EXTRACT(EPOCH FROM (MAX(event_time) - MIN(event_time))) AS duration_sec
FROM sessions
GROUP BY user_id, session_num
ORDER BY user_id, session_num;Логика: если промежуток между событиями больше 30 минут — начинается новая сессия. Кумулятивная сумма флагов даёт номер сессии.
Сессии на пользователя
WITH sessions AS (
SELECT user_id, COUNT(DISTINCT session_num) AS sessions
FROM (
SELECT
user_id,
SUM(is_new_session) OVER (PARTITION BY user_id ORDER BY event_time) AS session_num
FROM (
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_new_session
FROM events
WHERE event_time >= CURRENT_DATE - INTERVAL '30 days'
) x
) y
GROUP BY user_id
)
SELECT
AVG(sessions) AS avg_sessions_per_user,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY sessions) AS median_sessions
FROM sessions;Средняя длительность сессии
-- Используя CTE sessions из примера выше
SELECT
AVG(duration_sec) AS avg_duration_sec,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY duration_sec) AS median_duration_sec
FROM sessions
WHERE duration_sec > 0;Частые ошибки
Ошибка 1. Таймаут 30 минут — это не закон. Для B2B SaaS 30 минут — нормально, для стримов это 4+ часа, для игр — около часа. Значение таймаута согласуйте под свой продукт.
Ошибка 2. Сессии на разных устройствах. Пользователь начал на телефоне, продолжил на ПК — это две разные сессии или одна? Зависит от того, объединяете ли вы user_id между устройствами.
Ошибка 3. Не считать одиночные (singleton) сессии. Пользователь зашёл, сделал одно событие и ушёл. Это валидная сессия с длительностью 0 — не выбрасывайте её.
Ошибка 4. NULL в event_time. Очистите такие строки перед sessionization.
Ошибка 5. Игнорировать часовой пояс. Сессия, начавшаяся в полночь по UTC, может «разорваться» при пересчёте в локальный часовой пояс.
Связанные темы
- Как посчитать DAU в SQL
- Как посчитать MAU в SQL
- Как посчитать bounce rate в SQL
- Оконные функции в SQL — шпаргалка
FAQ
Какой таймаут считается стандартом?
Стандартом де-факто считаются 30 минут — именно такой таймаут по умолчанию стоит в Google Analytics. Большинство аналитиков отталкиваются от этого значения, но при необходимости подстраивают его под свой продукт.
Сколько сессий на пользователя — это норма?
Универсальной нормы нет, всё зависит от типа продукта. Для соцсети это порядка 5–15 сессий в неделю, для SaaS — 2–5 в неделю, для e-commerce — 1–3 в месяц.
Смотреть среднюю или медианную длительность?
Смотреть стоит обе. Среднее чувствительно к выбросам — например, пользователь не закрыл вкладку, и длительность сессии раздувается, поэтому медиана надёжнее описывает типичную сессию.
Как считать сессии на разных устройствах?
Объединить сессии с разных устройств можно, только если у вас есть сквозной user_id — обычно это возможно при логине. Без единого идентификатора каждое устройство считается отдельным пользователем.
Одиночные сессии — выбрасывать?
Нет, выбрасывать не нужно — считайте их отдельно. Высокая доля одиночных (singleton) сессий по сути и есть bounce rate: люди заходят и сразу уходят.