SQL: Найти сессии длиннее среднего для пользователя
Условие
У вас есть таблица sessions:
- session_id (integer)
- user_id (integer)
- session_date (date)
- duration_seconds (integer)
Для каждой сессии определите, была ли она длиннее средней сессии этого пользователя.
Ожидаемый результат:
Таблица с колонками:
- session_id
- user_id
- duration_seconds
- user_avg_duration (средняя длительность сессий пользователя)
- is_above_average (true/false)
Источник: типовая задача на оконные функции
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
Это задача на применение оконных функций для сравнения значений со статистикой по группам.
SQL запрос:
SELECT
session_id,
user_id,
duration_seconds,
ROUND(AVG(duration_seconds) OVER (PARTITION BY user_id), 2) as user_avg_duration,
duration_seconds > AVG(duration_seconds) OVER (PARTITION BY user_id) as is_above_average
FROM sessions
ORDER BY user_id, session_date;
Как это работает:
AVG(duration_seconds) OVER (PARTITION BY user_id) вычисляет среднюю длительность сессии для каждого пользователя. Это оконная функция, которая сохраняет детальность данных — не агрегирует все в одну строку, а применяет функцию в контексте каждой строки.
Сравнение duration_seconds > AVG(...) OVER (...) возвращает TRUE если сессия длиннее среднего, FALSE иначе.
Альтернативный вариант с CASE:
SELECT
session_id,
user_id,
duration_seconds,
ROUND(AVG(duration_seconds) OVER (PARTITION BY user_id), 2) as user_avg_duration,
CASE
WHEN duration_seconds > AVG(duration_seconds) OVER (PARTITION BY user_id)
THEN true
ELSE false
END as is_above_average
FROM sessions;
Расширенный вариант с дополнительными метриками:
SELECT
session_id,
user_id,
duration_seconds,
ROUND(AVG(duration_seconds) OVER (PARTITION BY user_id), 2) as user_avg_duration,
duration_seconds > AVG(duration_seconds) OVER (PARTITION BY user_id) as is_above_average,
ROUND(duration_seconds - AVG(duration_seconds) OVER (PARTITION BY user_id), 2) as diff_from_avg,
MAX(duration_seconds) OVER (PARTITION BY user_id) as user_max_duration,
MIN(duration_seconds) OVER (PARTITION BY user_id) as user_min_duration
FROM sessions
ORDER BY user_id, duration_seconds DESC;
Ключевые моменты:
- PARTITION BY user_id — разбивает данные на группы по пользователям
- OVER (PARTITION BY...) — применяет функцию внутри каждой партиции
- Результат остаётся строка на строку, не удаляя детали
- Эффективно для больших объёмов данных в аналитике
Этот запрос используется для выявления "выбросов" в поведении пользователя и анализа аномалий.
Похожие вопросы
- Продуктовый кейс: Анализ аномалии в метриках
- SQL: Ранжирование заказов клиента
- SQL: Найти пользователей с непрерывной активностью N дней
- Продуктовый кейс: Метрики для любимого приложения
- SQL: Найти топ-3 продукта по выручке в каждой категории
- SQL: Посчитать воронку конверсии
- SQL: Посчитать DAU и WAU
- SQL: Скользящее среднее за 7 дней
- SQL: Найти товары, которые покупали вместе
- SQL: Анализ повторных покупок
- SQL: Year-over-Year сравнение выручки
- SQL: Расчет конверсии по шагам регистрации
- SQL: Найти товары с падением продаж
- SQL: Вывести третью страницу для каждого пользователя
- SQL: Расчет времени до первой покупки
- Продуктовый кейс: Запуск новой страны
- SQL: Найти первую и последнюю покупку каждого клиента
- SQL: Найти пользователей с регулярными платежами
- SQL: Расчет ARPU по источникам трафика
- SQL: Процентиль выручки по клиентам