Как посчитать Returning Users в SQL
Содержание:
Зачем Returning Users
DAU 100K — вроде бы хорошо. Но: 70K новых, 30K вернувшихся. Через месяц новые падают (закончилась реклама), и DAU становится 30K. Доля вернувшихся — здоровый сигнал устойчивости бизнеса.
Что такое Returning
Returning User — активный за период, чья первая активность была ДО начала периода.
Returning ∈ period: first_activity < period_start AND has_activity_in_periodБазовый расчёт
WITH first_activity AS (
SELECT user_id, MIN(event_date) AS first_date
FROM events
GROUP BY user_id
)
SELECT
DATE_TRUNC('month', e.event_date) AS month,
COUNT(DISTINCT CASE
WHEN fa.first_date < DATE_TRUNC('month', e.event_date)
THEN e.user_id
END) AS returning_users,
COUNT(DISTINCT CASE
WHEN fa.first_date >= DATE_TRUNC('month', e.event_date)
AND fa.first_date < DATE_TRUNC('month', e.event_date) + INTERVAL '1 month'
THEN e.user_id
END) AS new_users,
COUNT(DISTINCT e.user_id) AS total_active
FROM events e
JOIN first_activity fa ON fa.user_id = e.user_id
WHERE e.event_date >= '2026-01-01'
GROUP BY 1
ORDER BY 1;Returning vs New vs Reactivated
| Тип | Определение |
|---|---|
| New | Первая активность ∈ period |
| Returning | Был активен сразу до period |
| Reactivated | Был активен давно, потом был неактивен X+ дней, вернулся в period |
WITH user_state AS (
SELECT
user_id,
MIN(event_date) AS first_date,
MAX(CASE WHEN event_date < '2026-04-01' THEN event_date END) AS last_before_period,
MIN(CASE WHEN event_date >= '2026-04-01' AND event_date < '2026-05-01' THEN event_date END) AS first_in_period
FROM events
GROUP BY user_id
)
SELECT
CASE
WHEN first_date >= '2026-04-01' AND first_date < '2026-05-01' THEN 'new'
WHEN last_before_period >= '2026-03-01' THEN 'returning'
WHEN last_before_period IS NOT NULL THEN 'reactivated'
END AS user_type,
COUNT(*) AS users
FROM user_state
WHERE first_in_period IS NOT NULL
GROUP BY 1;Разрезы
По сегментам и каналам:
SELECT
u.acquisition_channel,
COUNT(DISTINCT CASE
WHEN MIN(e.event_date) OVER (PARTITION BY e.user_id) < DATE_TRUNC('month', CURRENT_DATE)
THEN e.user_id
END) AS returning_users
FROM events e
JOIN users u ON u.user_id = e.user_id
WHERE e.event_date >= DATE_TRUNC('month', CURRENT_DATE)
GROUP BY u.acquisition_channel;Частые ошибки
Ошибка 1. Returning = всё, что не new. В такой логике reactivated засчитывается как returning. Разделяйте эти группы.
Ошибка 2. Граничные случаи. Пользователь с first_date = period_start — это new или returning? Договоритесь заранее.
Ошибка 3. Разные устройства. Без единого user_id новое устройство засчитывается как «new». Учитывайте это.
Ошибка 4. NOT IN с NULL. Такой запрос ломается. Используйте NOT EXISTS.
Ошибка 5. Сравнение returning между периодами без нормализации. Пользователь в апреле — «returning», если был активен в марте. В мае он может стать «reactivated», если в апреле не заходил. Тип пользователя меняется от периода к периоду.
Связанные темы
- Как посчитать new users в SQL
- Как посчитать reactivation в SQL
- Как посчитать retention в SQL
- Как посчитать DAU в SQL
FAQ
Чем Returning отличается от Reactivated?
Returning — пользователь был активен недавно, в пределах порога неактивности. Reactivated — вернулся после долгого отсутствия.
Какая доля Returning считается хорошей?
Зависит от стадии роста. У стартапа в фазе бурного роста новых пользователей больше, чем вернувшихся. У зрелого продукта вернувшихся значительно больше, чем новых.
Returning DAU падает — что делать?
Скорее всего дело в удержании или вовлечённости. Разложите метрику по когортам и найдите, где именно теряете вернувшихся.
Учитывать разные устройства обязательно?
Желательно. Без объединения профилей вы завышаете число new и занижаете returning.
Returning стабильный, new упал — что делать?
Проблема в привлечении — в маркетинге или SEO. Сама база вернувшихся при этом здоровая, так что чинить нужно верх воронки.