Как посчитать Sessions в SQL

Проверь себя · 1/3разбор после ответа
В таблице 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;
Закрепи формулу sessions в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать sessions в Telegram

Средняя длительность сессии

-- Используя 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, может «разорваться» при пересчёте в локальный часовой пояс.

Связанные темы

FAQ

Какой таймаут считается стандартом?

Стандартом де-факто считаются 30 минут — именно такой таймаут по умолчанию стоит в Google Analytics. Большинство аналитиков отталкиваются от этого значения, но при необходимости подстраивают его под свой продукт.

Сколько сессий на пользователя — это норма?

Универсальной нормы нет, всё зависит от типа продукта. Для соцсети это порядка 5–15 сессий в неделю, для SaaS — 2–5 в неделю, для e-commerce — 1–3 в месяц.

Смотреть среднюю или медианную длительность?

Смотреть стоит обе. Среднее чувствительно к выбросам — например, пользователь не закрыл вкладку, и длительность сессии раздувается, поэтому медиана надёжнее описывает типичную сессию.

Как считать сессии на разных устройствах?

Объединить сессии с разных устройств можно, только если у вас есть сквозной user_id — обычно это возможно при логине. Без единого идентификатора каждое устройство считается отдельным пользователем.

Одиночные сессии — выбрасывать?

Нет, выбрасывать не нужно — считайте их отдельно. Высокая доля одиночных (singleton) сессий по сути и есть bounce rate: люди заходят и сразу уходят.