PrepBro
Профессии
PrepBro
Профессия:

Подготовка

  • Вопросы298
  • Задачи60

Аналитика

  • hh статистика
  • Анализ резюме

Практика

  • Тестовое собеседование
  • Mock-собеседование
  • Менторы

Поддержка / отзывы

Telegram админа
Профессия:

Подготовка

  • Вопросы298
  • Задачи60

Аналитика

  • hh статистика
  • Анализ резюме

Практика

  • Тестовое собеседование
  • Mock-собеседование
  • Менторы

Поддержка / отзывы

Telegram админа
Все 24 профессии
Android DeveloperData AnalystSystem Analyst1С DeveloperiOS DeveloperBusiness AnalystJava DeveloperData ScientistQA EngineerQA AutomationPHP BackendC/C++ BackendDevOps EngineerIT Project ManagerFrontend DeveloperNode.js BackendUnity DeveloperC# BackendProduct AnalystFlutter DeveloperPython DeveloperIT Product ManagerGo DeveloperData Engineer

© 2026 PrepBro. Все права защищены.

Telegram-бот

Задачи по Product Analyst

Задачи с собеседований на продуктового аналитика: SQL на воронку конверсии, retention и когорты, LTV и ARPU, оконные функции и сессионизацию событий, продуктовые кейсы про падение конверсии и рост DAU, дизайн A/B-теста и размер выборки. К каждой задаче есть разбор с запросом или расчётом.

Продуктовый кейс: Анализ push-уведомлений
2.3 Middle🔥 30💬 1

Анализ push-уведомлений: метрики и оптимизация

1. Метрики push-уведомлений

Delivery метрики:

  • Delivery rate: % успешно доставленных push (целевой: >95%)
  • Bounce rate: % не доставленных (device offline, no permission)
  • Send time optimization: % отправленных в оптимальное время

Engagement метрики:

  • Open rate: % пользователей, открывших push (5-10% норма)
  • Click rate: % кликнувших по ссылке из push (2-5% норма)
  • Conversion rate: % совершивших целевое действие (1-3% норма)
  • Uninstall rate: % удаливших приложение после push

Качество и безопасность:

  • Opt-in rate: % пользователей, разрешивших push (целевой: >70%)
  • Opt-out rate: % отписавшихся после push (целевой: <2%)
  • Complaint rate: % пожаловавшихся на спам
  • Delivery latency: время от отправки до получения (целевой: <30сек)

2. Измерение влияния push на retention

Читать полностью ->
Продуктовый кейс: Оптимизация онбординга
3.0 Senior🔥 30💬 1

Анализ онбординга: Оптимизация воронки активации

Проблема 70% отсева на регистрации критична — это означает потерю 7 из 10 потенциальных пользователей на самом раннем этапе. Систематизирую подход анализа.

1. Данные для анализа

Запрошу иерархический набор данных:

На уровне воронки (aggregate):

  • Общее количество вошедших в онбординг vs завершивших регистрацию
  • Временные диапазоны (по датам, часам, дням недели)
  • Источники трафика (organic, paid, referral, direct)
  • Устройства и ОС (iOS, Android, Web)

На уровне шагов:

  • Для каждого шага регистрации: вход, выход, bounce-rate
  • Время прохождения каждого шага (абс. значения и квантили)
  • Причины выхода пользователей (если есть logs, events)

На уровне когорт:

  • Демография: страна, язык, возрастные группы
  • Поведение: количество попыток, повторные входы
  • Устройства: размер экрана, ОС версия, браузер
Читать полностью ->
SQL: Посчитать воронку конверсии
2.0 Middle🔥 29💬 1

Решение

Понимание задачи

Воронка конверсии показывает, на каком шаге пользователи отсеиваются:

  • Сколько пользователей просмотрели товар (view)
  • Из них сколько добавили в корзину (add_to_cart)
  • Из них сколько прошли к оплате (checkout)
  • Из них сколько совершили покупку (purchase)

SQL-запрос

Читать полностью ->
SQL: Расчет среднего чека по дням недели
1.0 Junior🔥 28💬 1

Расчет среднего чека по дням недели

Решение на PostgreSQL:

SELECT 
    TO_CHAR(order_date, 'Day') AS day_of_week,
    COUNT(*) AS orders_count,
    ROUND(AVG(total_amount)::numeric, 2) AS avg_order_amount,
    ROUND(SUM(total_amount)::numeric, 2) AS total_revenue
FROM orders
GROUP BY TO_CHAR(order_date, 'Day')
ORDER BY 
    CASE WHEN TO_CHAR(order_date, 'Day') = 'Monday' THEN 1
         WHEN TO_CHAR(order_date, 'Day') = 'Tuesday' THEN 2
         WHEN TO_CHAR(order_date, 'Day') = 'Wednesday' THEN 3
         WHEN TO_CHAR(order_date, 'Day') = 'Thursday' THEN 4
         WHEN TO_CHAR(order_date, 'Day') = 'Friday' THEN 5
         WHEN TO_CHAR(order_date, 'Day') = 'Saturday' THEN 6
         WHEN TO_CHAR(order_date, 'Day') = 'Sunday' THEN 7
    END;

Лучше с EXTRACT:

Читать полностью ->
SQL: Сравнение конверсии между устройствами
1.0 Junior🔥 27💬 1

Решение

Это задача на сравнительный анализ по типам устройств — критична для оптимизации мобильного опыта.

SQL запрос для сравнения по устройствам:

SELECT 
  s.device_type,
  COUNT(DISTINCT s.session_id) as sessions_count,
  COUNT(DISTINCT CASE WHEN c.session_id IS NOT NULL THEN s.session_id END) as conversions_count,
  ROUND(100.0 * COUNT(DISTINCT CASE WHEN c.session_id IS NOT NULL THEN s.session_id END) / COUNT(DISTINCT s.session_id), 2) as conversion_rate,
  ROUND(AVG(c.revenue), 2) as avg_revenue,
  ROUND(SUM(c.revenue) / COUNT(DISTINCT s.session_id), 2) as revenue_per_session
FROM sessions s
LEFT JOIN conversions c ON s.session_id = c.session_id
GROUP BY s.device_type
ORDER BY conversion_rate DESC;

Вариант с дополнительной аналитикой:

Читать полностью ->
SQL: Найти отток клиентов (Churn)
2.3 Middle🔥 27💬 1

SQL: Найти отток клиентов (Churn)

Определение Churn

Churn Rate — доля пользователей, которые не были активны в течение 30 дней от последней активности.

Решение 1: Базовый churn (пользователи неактивные 30+ дней)

WITH last_activity AS (
    SELECT user_id, MAX(activity_date) as last_active_date
    FROM user_activity
    GROUP BY user_id
)
SELECT
    DATE_TRUNC(NOW(), MONTH) as month,
    COUNT(*) as active_users,
    SUM(CASE WHEN DATE_DIFF(NOW(), last_active_date) >= 30 THEN 1 ELSE 0 END) as churned_users,
    ROUND(100.0 * SUM(CASE WHEN DATE_DIFF(NOW(), last_active_date) >= 30 THEN 1 ELSE 0 END) / COUNT(*), 2) as churn_rate
FROM last_activity;

Решение 2: Месячный когортный churn (более точный)

Читать полностью ->
SQL: Определить самый популярный день для покупок
1.0 Junior🔥 27💬 1

SQL: Определить самый популярный день для покупок

Анализ по дням недели

SELECT
    DAYNAME(order_date) as day_of_week,
    DAYOFWEEK(order_date) as day_num,
    COUNT(*) as orders_count,
    ROUND(SUM(amount), 2) as total_revenue,
    ROUND(AVG(amount), 2) as avg_order_value,
    ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER (), 2) as pct_of_total
FROM orders
GROUP BY DAYOFWEEK(order_date), DAYNAME(order_date)
ORDER BY day_num;

Анализ по часам суток

SELECT
    HOUR(order_date) as hour_of_day,
    COUNT(*) as orders_count,
    ROUND(SUM(amount), 2) as total_revenue,
    ROUND(AVG(amount), 2) as avg_order_value,
    ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER (), 2) as pct_of_total
FROM orders
GROUP BY HOUR(order_date)
ORDER BY hour_of_day;

Комбинированный анализ (день × час)

Читать полностью ->
SQL: Найти пользователей, купивших товар с id=5 после 10 октября
1.0 Junior🔥 27💬 1

Решение: Пользователи, купившие товар с id=5

Базовый SQL-запрос

SELECT COUNT(DISTINCT user_id) as unique_users
FROM purchases
WHERE product_id = 5
  AND purchase_date >= '2021-10-10';

Объяснение

Ключевые элементы:

  1. COUNT(DISTINCT user_id) — считаем уникальных пользователей

    • DISTINCT убирает дубликаты (если один пользователь купил товар дважды, считаем один раз)
    • Если просто COUNT(*), получим количество покупок, а не пользователей
  2. WHERE product_id = 5 — фильтруем только товар с id=5

  3. WHERE purchase_date >= '2021-10-10' — дата 10 октября 2021 включительно

    • Оператор >= означает "больше или равно", что включает саму дату 10.10.2021

Пример

Читать полностью ->
SQL: Расчет среднего размера корзины
1.0 Junior🔥 25💬 1

Решение

Это задача на анализ параметров заказов (basket size) — критична для e-commerce аналитики и оптимизации среднего чека.

Логика решения:

  1. Группируем товары по заказам — считаем количество товаров и сумму в каждом заказе
  2. Рассчитываем общие метрики — среднее количество товаров и средний чек
  3. Строим распределение — сколько заказов с 1 товаром, 2 товарами и т.д.

SQL запрос для общих метрик:

Читать полностью ->
SQL: Посчитать DAU и WAU
2.0 Middle🔥 25💬 1

SQL: Посчитать DAU и WAU

Объяснение метрик

DAU (Daily Active Users) — количество уникальных пользователей, выполнивших хотя бы одно действие в течение дня. Это базовая метрика для оценки ежедневной активности сервиса.

WAU (Weekly Active Users) — количество уникальных пользователей, выполнивших хотя бы одно действие на протяжении последних 7 дней (включая текущий день). Эта метрика показывает масштаб аудитории с недельным горизонтом и менее подвержена ежедневным колебаниям.

Решение с оконными функциями

SELECT
    activity_date as date,
    COUNT(DISTINCT user_id) as dau,
    COUNT(DISTINCT user_id) OVER (
        ORDER BY activity_date 
        ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
    ) as wau
FROM user_activity
GROUP BY activity_date
ORDER BY activity_date;
Читать полностью ->
SQL: Найти товары, которые покупали вместе
2.0 Middle🔥 25💬 1

Решение

Это задача на анализ сочетаний товаров (market basket analysis) — критична для e-commerce для рекомендаций и кросс-селлинга.

Логика решения:

  1. Соединяем order_items саму с собой — по order_id для нахождения товаров в одном заказе
  2. Исключаем одинаковые товары — нам нужны только пары разных товаров
  3. Избегаем дубликатов — условием product_id_1 < product_id_2
  4. Считаем частоту — количество заказов с обеими товарами
  5. Сортируем и ограничиваем — топ-10 по популярности

SQL запрос:

SELECT 
  oi1.product_id as product_id_1,
  oi2.product_id as product_id_2,
  COUNT(DISTINCT oi1.order_id) as times_bought_together
FROM order_items oi1
INNER JOIN order_items oi2 
  ON oi1.order_id = oi2.order_id 
  AND oi1.product_id < oi2.product_id
GROUP BY oi1.product_id, oi2.product_id
ORDER BY times_bought_together DESC
LIMIT 10;

Альтернативный подход (более явный):

Читать полностью ->
SQL: Скользящее среднее за 7 дней
2.0 Middle🔥 25💬 1

Решение: Скользящее среднее за 7 дней

SQL-запрос (базовый вариант)

SELECT
  date,
  revenue,
  ROUND(
    AVG(revenue) OVER (
      ORDER BY date 
      ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
    ), 2
  ) as moving_avg_7d
FROM daily_metrics
ORDER BY date;

Объяснение

Оконная функция AVG() OVER():

AVG(revenue) OVER (
  ORDER BY date                          -- Сортируем по дате
  ROWS BETWEEN 6 PRECEDING AND CURRENT ROW  -- Берём текущую и 6 предыдущих строк
)

Как это работает:

  • ORDER BY date — задаёт порядок обхода строк
  • ROWS BETWEEN 6 PRECEDING AND CURRENT ROW — окно включает:
    • 6 предыдущих дней (PRECEDING)
    • Текущий день (CURRENT ROW)
    • Итого: 7 дней

Почему "6 PRECEDING"?

  • 6 дней до текущего дня
    • 1 текущий день
  • = 7 дней всего

Пример

Читать полностью ->
SQL: Найти клиентов с более чем 3 покупками за месяц
1.3 Junior🔥 25💬 1

Решение: Клиенты с более чем 3 покупками за месяц

SQL-запрос

SELECT
  customer_id,
  COUNT(order_id) as orders_count,
  ROUND(SUM(amount), 2) as total_amount
FROM orders
WHERE order_date >= DATE_TRUNC('month', CURRENT_DATE) - INTERVAL '1 month'
  AND order_date < DATE_TRUNC('month', CURRENT_DATE) + INTERVAL '1 month'
GROUP BY customer_id
HAVING COUNT(order_id) > 3
ORDER BY orders_count DESC;

Альтернативный вариант (более универсальный)

WITH last_month AS (
  SELECT
    customer_id,
    COUNT(order_id) as orders_count,
    SUM(amount) as total_amount
  FROM orders
  WHERE order_date >= CURRENT_DATE - INTERVAL '30 days'
  GROUP BY customer_id
  HAVING COUNT(order_id) > 3
)
SELECT
  customer_id,
  orders_count,
  ROUND(total_amount, 2) as total_amount
FROM last_month
ORDER BY orders_count DESC;

Объяснение

Ключевые элементы:

Читать полностью ->
Вероятность: Задача про email рассылку
1.2 Junior🔥 24💬 1

Анализ email рассылки: вероятность и конверсия

1. Вероятность покупки для случайного получателя

Покупка произойдёт, если выполнены ВСЕ условия по цепочке:

Цепочка действий:

  1. Письмо открыто (25%)
  2. И по ссылке кликнули (10% от открывших)
  3. И произошла покупка (5% от кликнувших)

Расчёт (правило произведения вероятностей):

P(покупка) = P(открыт) × P(клик|открыт) × P(покупка|клик)
P(покупка) = 0.25 × 0.10 × 0.05 = 0.000125 = 0.0125%

Вероятность того, что случайный получатель совершит покупку = 0.0125% или 1 из 8000

2. Ожидаемое количество покупок

Расчёт по цепочке:

Этап 1: Открытия писем
10,000 × 0.25 = 2,500 пользователей открыли письмо

Этап 2: Клики
2,500 × 0.10 = 250 пользователей кликнули по ссылке

Этап 3: Покупки
250 × 0.05 = 12.5 ≈ 12-13 покупок ожидается

Или прямая формула:

Покупки = 10,000 × 0.25 × 0.10 × 0.05 = 12.5 ≈ 12 покупок

Ожидаемое количество покупок = 12-13 покупок

Читать полностью ->
SQL: Анализ повторных покупок
2.0 Middle🔥 24💬 1

Анализ повторных покупок

1. Один заказ

Количество клиентов, сделавших только одну покупку:

SELECT COUNT(customer_id) as one_time_buyers
FROM (SELECT customer_id, COUNT(*) FROM orders GROUP BY customer_id HAVING COUNT(*) = 1) t;

2. Повторные покупки

Процент клиентов с повторными покупками:

WITH customer_counts AS (
  SELECT customer_id, COUNT(*) as cnt FROM orders GROUP BY customer_id
)
SELECT 
  ROUND(100.0 * SUM(CASE WHEN cnt > 1 THEN 1 ELSE 0 END) / COUNT(*), 2) as repeat_rate
FROM customer_counts;

3. Среднее время между заказами

WITH ranked AS (
  SELECT customer_id, order_date, LAG(order_date) OVER (PARTITION BY customer_id ORDER BY order_date) as prev_date
  FROM orders
),
intervals AS (
  SELECT EXTRACT(DAY FROM (order_date - prev_date))::int as days_between
  FROM ranked WHERE prev_date IS NOT NULL
)
SELECT ROUND(AVG(days_between), 1) as avg_days_between_orders
FROM intervals;
Читать полностью ->
Статистика: Размер выборки для A/B теста
3.0 Senior🔥 24💬 1

Решение

Дано:

  • Baseline конверсия (p0) = 5%
  • Минимальный эффект = 10% относительный прирост → новая конверсия = 5.5%
  • Power = 80% (z_beta = 0.84)
  • Alpha = 5% (z_alpha = 1.96, двухсторонний)

Формула размера выборки:

n = (z_alpha + z_beta)² × [p0(1-p0) + p1(1-p1)] / (p1 - p0)²

Расчет:

  1. Z-критерии: (1.96 + 0.84)² = 7.84
  2. Вариабельность: 0.05×0.95 + 0.055×0.945 = 0.0995
  3. Разница: (0.055 - 0.05)² = 0.000025
  4. Результат: n = (7.84 × 0.0995) / 0.000025 = 31,160 на группу

Итоговые результаты:

1. Минимальный размер выборки:

  • Control группа: 31,160 пользователей
  • Variant группа: 31,160 пользователей
  • Всего: 62,320 пользователей

2. Параметры статистической значимости:

  • Уровень значимости α = 5% (p-value < 0.05)
  • Статистическая мощность = 80% (20% риск Type II ошибки)
  • Двухсторонний тест

3. Длительность теста:

Дни = 62,320 пользователей / 10,000 пользователей в день = 6.2 дня

Рекомендуемая длительность: 7 дней

Читать полностью ->
Продуктовый кейс: Метрики мессенджера
2.7 Senior🔥 24💬 1

Метрики мессенджера (Telegram-like)

1. Ключевые метрики роста и активности

Пользователи:

  • DAU (Daily Active Users) - логин + открыл чат
  • WAU/MAU - недельные и месячные
  • Day 1, 7, 30 Retention - % вернувшихся
  • New User Activation - % новых, которые отправили первое сообщение

Общение:

  • Messages Per DAU - среднее сообщений на активного пользователя в день
  • Unique Contacts Per User - у скольких людей пользователь переписывается
  • Conversation Starters - % пользователей, инициирующих новый диалог

Рост:

  • Viral Coefficient - сколько новых пользователей приносит каждый
  • Invite Accept Rate - % приглашений, которые приняли
  • Share Adoption - % шеров (ссылки, группы) в приложение

2. Вовлеченность (Engagement)

Интенсивность:

  • Messages Per User (всего / среднего активного)
  • Session Duration - среднее время в app
  • Session Frequency - раз в день пользователь открывает app
  • Time to First Message - как скоро после установки отправил сообщение
Читать полностью ->
SQL: Найти пользователей с непрерывной активностью N дней
1.8 Middle🔥 24💬 1

SQL: Найти пользователей с непрерывной активностью N дней

Объяснение подхода "Gaps and Islands"

Основная идея — сгруппировать непрерывные даты в "острова" (islands), отделённые "разрывами" (gap). Для этого используем хитрость: вычитаем из даты номер строки ROW_NUMBER(), получая "группу дней".

Логика: если дни идут подряд, разница между датой и ROW_NUMBER() будет одинаковой для всей последовательности.

Решение

Читать полностью ->
SQL: Расчет Retention Day 1, Day 7, Day 30
2.3 Middle🔥 24💬 1

Решение: Расчет Retention Day 1, Day 7, Day 30

Понимание метрики

Retention Day N — это процент пользователей, которые имели хотя бы одну сессию на N-й день после регистрации.

Пример:

  • Пользователь зарегистрировался 5 января 2024
  • Retention Day 1 = был ли он 6 января (на следующий день)?
  • Retention Day 7 = был ли он 12 января (через неделю)?
  • Retention Day 30 = был ли он 4 февраля (через месяц)?

SQL-запрос (базовый вариант)

Читать полностью ->
SQL: Расчет rolling retention
2.7 Senior🔥 23💬 1

Решение

Это задача на расчет rolling retention — метрика, которая показывает, какой % пользователей был активен в день N или позже.

Разница между обычной и rolling retention:

  • Normal Retention (Day 7): Был активен в точно день 7 (не раньше, не позже)
  • Rolling Retention (Day 7): Был активен где-то между днём 0 и днём 7

SQL запрос для rolling retention:

Читать полностью ->
Продуктовый кейс: Метрики игрового приложения
3.0 Senior🔥 23💬 1

Решение

Free-to-play игры — это уникальная категория, где нужно балансировать между монетизацией (заработок) и удержанием (размер аудитории). Приведу комплексный анализ.

1. Ключевые метрики для отслеживания

Метрики активности:

  • DAU (Daily Active Users) — игроки, открывших игру в день. Базовый показатель здоровья.
  • MAU (Monthly Active Users) — активные в месяц.
  • DAU/MAU ratio — "липкость". Для игр: > 0.25 = хорошо, > 0.4 = отлично.
  • Session Length — среднее время сессии (в минутах).
  • Sessions Per User Per Day — количество заходов в день. Для игр: 2-3 сессии = норма.
  • Returning Players (D1, D7, D30) — % игроков, вернувшихся через 1, 7, 30 дней.
Читать полностью ->
SQL: Медиана выручки по месяцам
2.2 Middle🔥 23💬 1

Решение

Это задача на расчет медианы (50-го процентиля) выручки по месяцам. Медиана часто информативнее среднего, так как не подвергается влиянию выбросов.

Логика решения:

  1. Группируем по месяцам — извлекаем месяц из даты
  2. Рассчитываем медиану — 50-й процентиль дневной выручки в каждом месяце
  3. Выводим результат — месяц и медиану

SQL запрос с PERCENTILE_CONT (PostgreSQL):

SELECT 
  DATE_TRUNC('month', date)::date as month,
  PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY revenue) as median_revenue
FROM daily_sales
GROUP BY DATE_TRUNC('month', date)
ORDER BY month;

Альтернативный подход с оконными функциями (универсальный):

Читать полностью ->
A/B тест: Дизайн эксперимента для кнопки оформления заказа
2.7 Senior🔥 23💬 1

Решение: A/B тест для цвета кнопки оформления заказа

1. Проектирование теста

Формулировка гипотезы

Нулевая гипотеза (H0): Цвет кнопки (зелёный vs оранжевый) не влияет на конверсию до покупки

Альтернативная гипотеза (H1): Оранжевая кнопка увеличивает конверсию до покупки на ≥5%

Обоснование 5% MDE:

  • Базовая конверсия на кнопку обычно ~2-5% (зависит от трафика)
  • 5% относительный лифт = практически значимо для бизнеса
  • Меньше чувствителен к noise
  • Требует разумный размер выборки

Дизайн теста

ТЕСТ: Button Color Optimization

GROUPS:
├─ Control (A):    Зелёная кнопка #4CAF50
├─ Treatment (B):  Оранжевая кнопка #FF9800
└─ Размер групп: 50/50 (рандомизация)

LEVEL OF RANDOMIZATION: User ID
├─ Не session (иначе один пользователь может быть в обеих группах)
└─ Sticky assignment: один пользователь в одной группе всегда

TARGET AUDIENCE: Все пользователи, прошедшие до checkout
Читать полностью ->
Продуктовый кейс: Анализ аномалии в метриках
1.7 Middle🔥 23💬 1

Решение: Анализ аномалии в метриках

Фреймворк анализа аномалий

При обнаружении аномалии в метриках нужно следовать структурированному подходу: сначала исключить технические и процессные причины, потом проверить внешние факторы, и только потом делать выводы о продукте.


1. Гипотезы для объяснения аномалии

Категория 1: Технические и операционные проблемы

Гипотеза 1.1: Технический сбой (downtime)

  • Сервер был недоступен, API работал нестабильно
  • Мобильное приложение получило плохой релиз
  • Платёжная система была неисправна

Гипотеза 1.2: Проблемы с отслеживанием данных

  • Аналитика была отключена или некорректна
  • Логирование событий сломалось
  • Фильтры в отчётах применены неправильно

Гипотеза 1.3: Изменение в расчётах метрик

  • Произошло обновление формулы расчёта
  • Изменились фильтры данных
  • Произошла миграция данных

Категория 2: Маркетинг и бизнес-события

Читать полностью ->
SQL: Построить когортную таблицу retention по месяцам
3.0 Senior🔥 23💬 1

Решение

###概念理解

Когортная таблица retention показывает, какой процент пользователей, зарегистрировавшихся в одном месяце (когорта), остались активны в последующие месяцы.

  • M0 — месяц регистрации
  • M1 — месяц через месяц после регистрации
  • M2 — два месяца спустя
  • И т.д.

SQL-запрос

Читать полностью ->
SQL: Анализ Customer Journey
2.4 Senior🔥 22💬 1

Решение: SQL-анализ Customer Journey

Бизнес-задача

Анализ путей, по которым пользователи приходят к конверсии. Это критично для оптимизации маркетинга: нужно понять, какие каналы и последовательности наиболее эффективны.

1. Самые частые последовательности касаний

Читать полностью ->
SQL: Year-over-Year сравнение выручки
2.0 Middle🔥 22💬 1

Year-over-Year сравнение выручки

Решение на PostgreSQL:

SELECT 
    DATE_TRUNC('month', month)::date AS month,
    revenue,
    LAG(revenue) OVER (
        ORDER BY DATE_TRUNC('month', month)
        RANGE BETWEEN INTERVAL '1 year' PRECEDING AND INTERVAL '1 year' PRECEDING
    ) AS prev_year_revenue,
    ROUND((
        (revenue - LAG(revenue) OVER (
            ORDER BY DATE_TRUNC('month', month)
            RANGE BETWEEN INTERVAL '1 year' PRECEDING AND INTERVAL '1 year' PRECEDING
        )) / LAG(revenue) OVER (
            ORDER BY DATE_TRUNC('month', month)
            RANGE BETWEEN INTERVAL '1 year' PRECEDING AND INTERVAL '1 year' PRECEDING
        ) * 100
    ), 2) AS yoy_change_pct
FROM monthly_revenue
ORDER BY month;

Более простой вариант с подзапросом:

Читать полностью ->
Продуктовый кейс: Рост DAU e-commerce приложения
2.8 Senior🔥 22💬 1

Продуктовый кейс: Рост DAU e-commerce приложения на 20%

1. Декомпозиция цели

DAU = Новые пользователи (D0→D1) + Вернувшиеся (Retention)
DAU_target = DAU_current × 1.20

Варианты декомпозиции:

  • Инсталлы +20% при неизменном ретеншене
  • Инсталлы +10%, D1 retention +9% (из расчёта на реактивацию)
  • Инсталлы +5%, D7 retention +10%, реактивация +5%

2. Рычаги влияния на DAU

Входящий поток (Acquisition):

  • Объём инсталлов (ASO, paid, organic)
  • D0 activation rate (сколько открывают на день установки)
  • First session quality (онбординг)

Удерживающий поток (Retention):

  • D1 Retention (вернулись на день 2)
  • D7 Retention (активны на неделю)
  • Monthly Frequency (дни активности в месяц)

Реактивация:

  • Win-back campaigns для неактивных (7-14 дней)
  • Качество уведомлений и персонализация

3. Гипотезы для роста

H1: Улучшение онбординга → D1 retention +8%

  • Упростить регистрацию, показать ценность в день 1
Читать полностью ->
Продуктовый кейс: Метрики для любимого приложения
1.8 Middle🔥 22💬 1

Решение: Telegram как Product Analyst

1. Бизнес-модель

Telegram использует комбинированную модель с несколькими потоками дохода:

Основные источники выручки:

  • Premium-подписка (~$100/год) — блокировка спама, наклейки, раскраски, приоритет в поддержке
  • Бизнес-аккаунты — расширенная аналитика и функции для коммерсантов
  • Реклама в каналах (запущена в 2022) — рекламные посты в рекомендуемых каналах
  • Владение аудиторией — косвенный доход через привлечение пользователей для клиентов

Косвенные выгоды:

  • Снижение зависимости от ВК, Facebook (альтернатива)
  • Укрепление позиции как защитника приватности
  • Данные пользовательского поведения для развития (но не продаются)

2. Ключевые метрики по бизнес-целям

Читать полностью ->
SQL: Найти товары с падением продаж
2.0 Middle🔥 21💬 1

Решение: SQL-запрос для анализа падения продаж

Постановка задачи

Необходимо найти товары, у которых еженедельные продажи упали более чем на 30% между двумя последовательными неделями. Это критический метрика для выявления проблемных товаров, требующих немедленного внимания.

Подход

Используем оконные функции (Window Functions) для сравнения данных разных недель. Этот подход позволяет вычислить суммы продаж за каждую неделю и сравнить их без сложных JOIN-ов.

SQL-запрос

Читать полностью ->
SQL: Ранжирование заказов клиента
1.7 Middle🔥 21💬 1

Ранжирование и сравнение заказов SQL

SELECT customer_id, order_id, order_date, amount, ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date) as order_number, LAG(amount) OVER (PARTITION BY customer_id ORDER BY order_date) as prev_order_amount, ROUND(amount - LAG(amount) OVER (PARTITION BY customer_id ORDER BY order_date), 2) as amount_change, ROUND(100.0 * (amount - LAG(amount) OVER (PARTITION BY customer_id ORDER BY order_date)) / LAG(amount) OVER (PARTITION BY customer_id ORDER BY order_date), 1) as percent_change FROM orders ORDER BY customer_id, order_date

Объяснение:

  • ROW_NUMBER: порядковый номер заказа для клиента
  • LAG: получаем сумму предыдущего заказа
  • amount_change: разница между текущим и предыдущим заказом
  • percent_change: процентное изменение (рост/падение чека)
Читать полностью ->
Продуктовый кейс: Улучшение retention D7
3.0 Senior🔥 21💬 1

Решение

Это финальный комплексный кейс на улучшение D7 retention с 15% до бенчмарка 25%.

1. Данные для анализа

Минимальный набор:

  • install_date, first_launch_date — когда установил
  • Day1, Day3, Day7 retention — показатели
  • utm_source, utm_campaign — источник
  • device_type, os_version, country — параметры
  • onboarding_completed — прошёл ли процесс
  • events_log — логика событий
  • crash_count, error_count — проблемы

2. Сегментация пользователей

По источнику трафика:

Organic: D7 = 20% ← Хорошо
Paid (Google): D7 = 12% ← ПРОБЛЕМА
Paid (Facebook): D7 = 14% ← ПРОБЛЕМА
Referral: D7 = 28% ← Отлично

По полноте онбординга:

Completed: D7 = 25% ← Хорошо
Partial: D7 = 10% ← КРИТИЧНО
No onboarding: D7 = 5% ← ОЧЕНЬ ПЛОХО

По активности день 1-3:

3+ сессии день 1: D7 = 40% ← Вовлечённые
1-2 сессии день 1: D7 = 18% ← Средние
0 сессий день 1: D7 = 2% ← Совсем ушли
Читать полностью ->
Продуктовый кейс: Метрики для подписочного сервиса
2.7 Senior🔥 21💬 1

Метрики для подписочного сервиса (Netflix/Spotify)

Подписочная модель отличается от других моделей монетизации: доход предсказуем, но нужно постоянно удерживать пользователей. Расскажу про систему метрик для такого сервиса.

1. Ключевые метрики для мониторинга

Метрики роста и базы

Subscribers (Active Subscribers)

  • Текущее количество активных подписчиков
  • Критична для инвесторов
  • Разбиваем по плану: Premium, Standard, Basic, Free Trial

New Subscriptions (New Sign-ups)

  • Количество новых подписчиков в период
  • Показывает эффективность маркетинга и onboarding
  • Тренд: растёт ли база?

Monthly Recurring Revenue (MRR)

  • Ежемесячный повторяющийся доход
  • MRR = (# активных подписчиков) * (средняя стоимость плана)
  • Для Netflix: если 100M подписчиков, avg $12/month = $1.2B MRR

Удержание и отток

Читать полностью ->
SQL: Расчет конверсии по шагам регистрации
2.0 Middle🔥 21💬 1

Решение

Задача на расчет фанел-метрик (funnel analytics) — одна из самых важных в Product Analytics. Воронка показывает, на каком этапе процесса пользователи выпадают.

Логика решения:

  1. Подсчитываем уникальных пользователей на каждом шаге — берём первое появление пользователя на каждом этапе
  2. Определяем порядок шагов — создаём иерархию регистрации
  3. Вычисляем конверсию — от начала и от предыдущего шага

SQL запрос:

Читать полностью ->
Продуктовый кейс: Падение конверсии
3.0 Senior🔥 21💬 1

Решение: Падение конверсии в e-commerce

Шаг 1: Выдвижение гипотез

Падение конверсии на 5 процентных пункта (с 15% до 10%) — существенное снижение. Причины могут быть технические, продуктовые, платёжные или внешние.

Технические гипотезы:

  • Проблемы с чекаутом — ошибки при отправке формы платежа, время загрузки > 3 сек
  • Баг мобильной версии — проблемы с вводом данных на смартфоне (35-50% трафика)
  • Проблемы с платёжными системами — сбои API платёжного провайдера, 3DS не работает
  • Несовместимость браузеров — старые версии IE, Edge не поддерживают платёж

Продуктовые гипотезы:

  • Изменение UI/UX — новый дизайн чекаута запутанный, скрыли важное поле
  • Удаление опции экспресс-платежа — ранее был один-клик платёж (Apple Pay, Google Pay)
  • Усложнение формы — добавили поля для сбора данных (телефон, адрес доставки)
  • Скрытые платежи — внезапно появились комиссии, которых раньше не было
Читать полностью ->
SQL: Расчет времени до первой покупки
2.0 Middle🔥 20💬 1

Решение

Это задача на расчет time-to-conversion — критична для понимания скорости монетизации и эффективности онбординга.

Логика решения:

  1. Находим первую покупку для каждого пользователя — MIN(order_date) по user_id
  2. Вычисляем разницу между registration_date и первой покупкой
  3. Анализируем распределение по количеству дней до первой покупки

SQL запрос для общей статистики:

Читать полностью ->
Продуктовый кейс: Метрики мобильного приложения такси
3.0 Senior🔥 20💬 1

Метрики приложения заказа такси

1. Ключевые метрики роста

Пассажиры:

  • DAU - количество заказов в день
  • Retention Rate (День 1, День 7, День 30) - возвращаются ли пассажиры
  • Frequency - средний заказов на пассажира в месяц
  • LTV - lifetime value за всё время
  • Payment Success Rate - успешные платежи

Водители:

  • DAU - активные водители в день
  • Hours Online - среднее время в сети
  • Earnings Per Hour - доход водителя
  • Acceptance Rate - % принятых заказов
  • Utilization - % времени выполнения заказов (не просто в сети)
  • Churn Rate - % уходящих водителей

2. Качество сервиса

  • Mean Time to Match < 20 сек (время от запроса до принятия)
  • Cancellation Rate - отмены до приезда (+ до начала поездки)
  • Average Rating (1-5 stars) - качество поездки
  • ETA Accuracy - насколько предсказанное время точно
  • No-show Rate - пассажир не появился
  • Complaint Rate - жалобы на водителя/пассажира

3. Метрики по сторонам

Читать полностью ->
SQL: Вывести третью страницу для каждого пользователя
2.0 Middle🔥 20💬 1

Решение

Описание подхода

Для решения этой задачи используем оконные функции (window functions) в SQL. Ключевая идея: присвоить каждой странице пользователя номер в хронологическом порядке и отфильтровать только те строки, где номер равен 3.

SQL-запрос

WITH ranked_pages AS (
  SELECT
    user_id,
    page,
    ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY time ASC) as page_number
  FROM log
)
SELECT user_id, page
FROM ranked_pages
WHERE page_number = 3

Почему этот подход работает

ROW_NUMBER() — оконная функция, которая нумерует строки в порядке, определённом в ORDER BY:

  • PARTITION BY user_id — нумерация независима для каждого пользователя
  • ORDER BY time ASC — нумерация в хронологическом порядке (от старых событий к новым)
  • WHERE page_number = 3 — берём только третьи строки

Альтернативный синтаксис (без CTE)

Если СУБД позволяет использовать WHERE на результаты window-функций:

Читать полностью ->
Продуктовый кейс: Запуск новой страны
2.0 Middle🔥 19💬 1

Аналитика запуска в новой стране: метрики и бенчмарки

1. Метрики для отслеживания запуска

Фаза 1: Тестирование и софт-запуск (1-2 недели)

  • Установки в день (Daily Installs)
  • Уникальные пользователи, запустившие приложение (DAU)
  • Процент завершивших onboarding
  • Ошибки и крахи (crash rate <0.5%)
  • Платежная система работает (success rate >98%)
  • Поддержка локального языка работает
  • Время загрузки в сети (latency <2сек)

Фаза 2: Полный запуск (неделя 3-12)

  • User acquisition: DAU, недельный приход новых пользователей
  • Engagement: D1, D7, D30 retention
  • Monetization: ARPU по стране, LTV
  • Platform distribution: % iOS vs Android
  • Content relevance: какие категории популярны

Фаза 3: Оптимизация (месяц 3+)

  • Market share vs конкурентов в стране
  • Geographic spread (города vs небольшие поселения)
  • Seasonal trends (праздники, сезоны)

2. Определение успешности запуска

Критерии успеха (KPI по фазам):

Читать полностью ->
SQL: Найти сессии длиннее среднего для пользователя
1.7 Middle🔥 19💬 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:

Читать полностью ->
Продуктовый кейс: Оценка успешности новой фичи
2.7 Senior🔥 19💬 1

Решение: Оценка успешности новой фичи

1. Как измерить успешность: Иерархия метрик

Уровень 1 — Первичный метрик (Primary Metric)

Выбор зависит от типа фичи, но принцип всегда одинаков: метрик должен быть связан с бизнес-целью.

Примеры:

  • Фича для удержания пользователей → D7/D30 Retention Rate
  • Фича для монетизации → Premium Conversion Rate или ARPU
  • Фича для вовлечённости → Time Spent in App или DAU
  • Фича для упрощения UX → Task Completion Rate или User Error Rate

Почему именно первичный метрик? Он напрямую влияет на стратегическую цель продукта. Если первичный метрик растёт, фича работает. Остальные метрики — для диагностики.

Уровень 2 — Вторичные метрики (Secondary Metrics)

Читать полностью ->
SQL: Найти пользователей с регулярными платежами
2.0 Middle🔥 18💬 1

Решение

Это задача на выявление регулярных плательщиков (recurring revenue users) — критична для MRR прогнозов в подписочных моделях.

Логика решения:

  1. Группируем платежи по пользователям и неделям — определяем, в какие недели платил пользователь
  2. Считаем количество недель с платежами — пользователь платил в 4 разные недели = регулярный
  3. Фильтруем по критериям — последний месяц, минимум 2+ недель

SQL запрос для выявления регулярных плательщиков:

Читать полностью ->
SQL: Найти первую и последнюю покупку каждого клиента
2.0 Middle🔥 18💬 1

Решение: Первая и последняя покупка клиента

SQL-запрос (базовый вариант)

SELECT
  customer_id,
  COUNT(*) as total_purchases,
  MIN(purchase_date) as first_purchase_date,
  MAX(purchase_date) as last_purchase_date
FROM purchases
GROUP BY customer_id
ORDER BY customer_id;

Это найдёт даты, но без информации о продуктах.

Вариант со страницей (с использованием оконных функций)

Читать полностью ->
SQL: Сессионизация событий
2.2 Middle🔥 17💬 1

Сессионизация событий SQL

WITH events_ranked AS ( SELECT user_id, event_id, event_time, LAG(event_time) OVER (PARTITION BY user_id ORDER BY event_time) as prev_time, CASE WHEN prev_time IS NULL THEN 1 WHEN EXTRACT(EPOCH FROM (event_time - prev_time)) / 60 > 30 THEN 1 ELSE 0 END as session_start FROM user_events ),

sessions AS ( SELECT user_id, event_id, event_time, CONCAT(user_id, '_', SUM(session_start) OVER (PARTITION BY user_id ORDER BY event_time)) as session_id FROM events_ranked )

SELECT user_id, session_id, MIN(event_time) as session_start, MAX(event_time) as session_end, COUNT(*) as events_in_session FROM sessions GROUP BY user_id, session_id

Объяснение:

  • LAG вычисляет время предыдущего события
  • Новая сессия начинается если это первое событие или >30 минут прошло
  • SUM() OVER создает приращивающийся счетчик для группировки
  • GROUP BY агрегирует события по сессиям
Читать полностью ->
SQL: Найти пользователей с максимальным чеком в каждом месяце
2.3 Middle🔥 17💬 1

Найти максимальный чек в каждом месяце

Используем MAX() window function для нахождения максимума в каждом месяце:

WITH max_monthly AS (
  SELECT 
    DATE_TRUNC('month', order_date) as month,
    user_id,
    total_amount,
    MAX(total_amount) OVER (PARTITION BY DATE_TRUNC('month', order_date)) as max_amt
  FROM orders
)
SELECT 
  month::date,
  user_id,
  total_amount as max_order_amount
FROM max_monthly
WHERE total_amount = max_amt
ORDER BY month, user_id;

Ключевые части:

  • MAX() OVER (PARTITION BY месяц) вычисляет максимум для каждого месяца
  • WHERE total_amount = max_amt оставляет только записи с максимальной суммой
  • Если несколько пользователей имеют одинаковый максимум, выведет всех

Альтернатива с RANK():

Читать полностью ->
Продуктовый кейс: Маркетплейс доставки еды
3.0 Senior🔥 16💬 1

Метрики трехстороннего маркетплейса доставки

1. Метрики ресторанов

  • Заказы/день, AOV (Average Order Value)
  • Время подготовки заказа (Prep Time)
  • % готовых в срок (>95%)
  • Рейтинг ресторана (целевой: >4.5/5)
  • Маржа: выручка минус расходы
  • % отмен рестораном (<1%)

2. Метрики курьеров

  • Заказы/день, средний доход
  • On-time delivery rate (>95%)
  • Рейтинг курьера (>4.2/5)
  • Чистая часовая ставка
  • Retention (DAU/MAU)
  • Completion rate

3. Метрики клиентов

  • DAU/MAU, Retention (D1/D7/D30)
  • ARPU, LTV, CAC
  • NPS (целевой: >50)
  • Customer satisfaction (>4.2/5)
  • Refund rate (<3%)

4. Здоровье экосистемы

  • GMV (Gross Merchandise Value)
  • On-time rate платформы (>95%)
  • NPS маркетплейса
  • Баланс роста трех сторон

5. Guardrail метрики

  • On-time >93% (не падать)
  • Satisfaction >4.2/5
  • Restaurant churn <15%
  • Courier earnings стабильны
  • GMV не падать >5%
Читать полностью ->
SQL: Расчет ARPU по источникам трафика
2.0 Middle🔥 16💬 1

SQL: Расчет ARPU по источникам трафика

Базовый расчет ARPU

SELECT
    u.traffic_source,
    COUNT(DISTINCT u.user_id) as users_count,
    ROUND(SUM(p.amount), 2) as total_revenue,
    ROUND(SUM(p.amount) / COUNT(DISTINCT u.user_id), 2) as arpu
FROM users u
LEFT JOIN payments p ON u.user_id = p.user_id
GROUP BY u.traffic_source
ORDER BY arpu DESC;

С учетом конверсии платящих пользователей

SELECT
    u.traffic_source,
    COUNT(DISTINCT u.user_id) as total_users,
    COUNT(DISTINCT p.user_id) as paying_users,
    ROUND(100.0 * COUNT(DISTINCT p.user_id) / COUNT(DISTINCT u.user_id), 2) as conversion_pct,
    ROUND(SUM(COALESCE(p.amount, 0)), 2) as total_revenue,
    ROUND(SUM(COALESCE(p.amount, 0)) / COUNT(DISTINCT u.user_id), 2) as arpu,
    ROUND(SUM(COALESCE(p.amount, 0)) / COUNT(DISTINCT p.user_id), 2) as arppu
FROM users u
LEFT JOIN payments p ON u.user_id = p.user_id
GROUP BY u.traffic_source
ORDER BY arpu DESC;
Читать полностью ->
SQL: Процентиль выручки по клиентам
2.0 Middle🔥 16💬 1

Решение

Это задача на разбиение клиентов по величине выручки с помощью оконных функций. Типичная сегментация для анализа VIP-клиентов.

Логика решения:

  1. Агрегируем заказы по клиентам — суммируем amount для каждого customer_id
  2. Применяем NTILE(4) — разбиваем на 4 равные группы по величине выручки
  3. Выводим результат — customer_id с квартилем

SQL запрос с NTILE:

WITH customer_totals AS (
  SELECT 
    customer_id,
    SUM(amount) as total_amount
  FROM orders
  GROUP BY customer_id
)
SELECT 
  customer_id,
  total_amount,
  NTILE(4) OVER (ORDER BY total_amount) as percentile
FROM customer_totals
ORDER BY total_amount DESC;

Альтернативный подход с PERCENT_RANK:

Читать полностью ->
SQL: Расчет LTV по когортам
2.0 Middle🔥 16💬 1

Решение: Расчет LTV по когортам

Понимание метрики

LTV (Lifetime Value) — это общая выручка, которую принёс один пользователь за всё время.

LTV по когортам — средняя выручка на пользователя по месяцам его регистрации.

Пример:

  • Когорта январь 2024: 1000 пользователей, выручка 500,000 руб → LTV = 500 руб/пользователя
  • Когорта февраль 2024: 1200 пользователей, выручка 840,000 руб → LTV = 700 руб/пользователя

SQL-запрос (базовый вариант)

SELECT
  DATE_TRUNC('month', u.registration_date)::date as registration_month,
  COUNT(DISTINCT u.user_id) as users_count,
  ROUND(SUM(COALESCE(p.amount, 0)), 2) as total_revenue,
  ROUND(SUM(COALESCE(p.amount, 0)) / COUNT(DISTINCT u.user_id), 2) as ltv
FROM users u
LEFT JOIN payments p ON u.user_id = p.user_id
GROUP BY DATE_TRUNC('month', u.registration_date)
ORDER BY registration_month;

Объяснение

Ключевые элементы:

Читать полностью ->
SQL: Cumulative sum (нарастающий итог)
2.0 Middle🔥 16💬 1

Решение: Cumulative Sum (нарастающий итог)

Объяснение задачи

Нужно для каждого пользователя посчитать running total — сумму всех транзакций с начала периода до текущей даты. Это классическая задача аналитиков для анализа накопления денег, расходов и т.д.

Синтаксис: Window Function

SQL предоставляет window function SUM() OVER() — идеальный инструмент для нарастающих итогов:

SELECT 
    user_id,
    transaction_date,
    amount,
    SUM(amount) OVER (
        PARTITION BY user_id 
        ORDER BY transaction_date
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS cumulative_sum
FROM transactions
ORDER BY user_id, transaction_date;

Разбор синтаксиса

PARTITION BY user_id — разделяет данные по пользователям. Каждый пользователь считается отдельно.

ORDER BY transaction_date — упорядочивает строки в партиции. Без этого cumulative sum не имеет смысла.

Читать полностью ->