Вопрос с собеседования · Аналитика данных

Как разбить поток событий на сессии на SQL?

MiddleSQL для аналитикаSQL
Ещё спрашивают так:
  • Как посчитать длительность сессии?
Коротко

Сессия — серия событий пользователя без пауз дольше порога (обычно 30 минут). LAG даёт время предыдущего события; где пауза больше порога — флаг начала новой сессии; нарастающая сумма флагов по пользователю — номер сессии. Дальше агрегаты по (пользователь, номер сессии).

  • Порог выбирают по распределению пауз, а не наугад
  • Сессии, пересекающие полночь, не режут по датам
  • Длительность сессии из одного события — ноль; это нужно учитывать в средних

А ещё Веб-аналитика (Яндекс Метрика, GA) определяет сессии по своим правилам — цифры могут не совпасть

Подробно

Выбор порога. Построить гистограмму пауз между соседними событиями пользователя: обычно видна «впадина» между короткими паузами внутри сессии и длинными между визитами. 30 минут — распространённое значение по умолчанию.

Тонкости: события с одинаковым временем — добавить второй ключ сортировки; события из разных устройств одного пользователя — решить, объединять ли; длительность считать до последнего события, а не до ухода — ухода мы не видим.

Пример

WITH marked AS (
  SELECT user_id, event_time,
         CASE WHEN event_time - LAG(event_time) OVER w > INTERVAL '30 minutes'
                OR LAG(event_time) OVER w IS NULL THEN 1 ELSE 0 END AS new_session
  FROM events
  WINDOW w AS (PARTITION BY user_id ORDER BY event_time)
),
numbered AS (
  SELECT *, SUM(new_session) OVER (PARTITION BY user_id ORDER BY event_time
                                   ROWS UNBOUNDED PRECEDING) AS session_no
  FROM marked
)
SELECT user_id, session_no,
       MIN(event_time) AS started,
       MAX(event_time) - MIN(event_time) AS duration,
       COUNT(*) AS events
FROM numbered
GROUP BY user_id, session_no;

Что хотят услышать

  • Флаг новой сессии через LAG и нарастающую сумму.
  • Выбор порога.
  • Ограничения: последнее событие, устройства.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓LAG, флаг при паузе больше порога, нарастающая сумма флагов — номер сессии
  • ✗Сессия — все события пользователя за календарный день: GROUP BY по user_id и дате события, а номер — ROW_NUMBER по дате
  • ✗Порог паузы всегда ровно пять минут: так его определяет стандарт веб-аналитики
  • ✗Сессии нужно резать по полуночи, иначе одна сессия попадёт сразу в два дня отчёта

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования