Как посчитать Repeat Buyer Rate в SQL

Проверь себя · 1/3разбор после ответа
Что делает оператор DISTINCT в SELECT-запросе?

Зачем Repeat Buyer Rate

Repeat Buyer — это покупатель, который совершил две и более покупки. Repeat Buyer Rate (доля таких покупателей) — базовая метрика e-commerce: она показывает, возвращаются ли люди за повторной покупкой, то есть насколько продукт реально нужен, а не куплен один раз под акцию. Привлечение нового клиента дорого стоит, поэтому повторные покупки — это, по сути, «бесплатная» выручка с уже оплаченного трафика, и рост этой метрики напрямую улучшает unit-экономику.

Формула

Repeat Buyer Rate = покупатели_с_2+_заказами / всего_покупателей × 100%

Окно наблюдения чаще всего берут 12 месяцев или lifetime (за всё время). Выбор окна критичен: одна и та же база даст разные цифры на 90 днях и за всю жизнь, поэтому окно фиксируют в определении метрики.

Базовый расчёт

Считаем число оплаченных заказов на покупателя и смотрим долю тех, у кого их два и больше:

WITH order_counts AS (
    SELECT
        user_id,
        COUNT(*) AS order_count
    FROM orders
    WHERE status = 'paid'
      AND created_at >= CURRENT_DATE - INTERVAL '12 months'
    GROUP BY user_id
)
SELECT
    COUNT(*) AS total_customers,
    COUNT(*) FILTER (WHERE order_count >= 2) AS repeat_buyers,
    COUNT(*) FILTER (WHERE order_count >= 2)::NUMERIC * 100 / COUNT(*) AS repeat_buyer_rate_pct
FROM order_counts;

Фильтр status = 'paid' важен: в знаменателе только реально оплатившие клиенты, отменённые и неоплаченные заказы в расчёт не идут. FILTER (WHERE order_count >= 2) отбирает повторных покупателей.

По когортам

Средний rate по всей базе обманчив: свежие покупатели физически не успели купить второй раз. Честнее считать долю повторных покупок по когорте месяца первой покупки:

WITH first_purchase AS (
    SELECT
        user_id,
        MIN(created_at) AS first_order_at
    FROM orders
    WHERE status = 'paid'
    GROUP BY user_id
),
cohort_repeat AS (
    SELECT
        DATE_TRUNC('month', fp.first_order_at) AS cohort,
        fp.user_id,
        COUNT(o.order_id) AS total_orders
    FROM first_purchase fp
    LEFT JOIN orders o ON o.user_id = fp.user_id
      AND o.status = 'paid'
      AND o.created_at <= fp.first_order_at + INTERVAL '12 months'
    WHERE fp.first_order_at >= CURRENT_DATE - INTERVAL '18 months'
      AND fp.first_order_at < CURRENT_DATE - INTERVAL '6 months'
    GROUP BY 1, fp.user_id
)
SELECT
    cohort,
    COUNT(*) AS customers,
    COUNT(*) FILTER (WHERE total_orders >= 2) AS repeat_buyers,
    COUNT(*) FILTER (WHERE total_orders >= 2)::NUMERIC * 100 / COUNT(*) AS repeat_rate_pct
FROM cohort_repeat
GROUP BY cohort
ORDER BY cohort;

Обратите внимание на два условия. Окно + INTERVAL '12 months' даёт каждой когорте одинаковый срок на повторную покупку. А фильтр по first_order_at < CURRENT_DATE - INTERVAL '6 months' отсекает слишком свежие когорты, у которых окно ещё не закрылось, — иначе сравнение было бы нечестным.

Время до второй покупки

Не менее важно, как быстро происходит вторая покупка — это подсказывает, когда включать реактивацию:

WITH ordered AS (
    SELECT
        user_id,
        created_at AS order_at,
        ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at) AS rn
    FROM orders
    WHERE status = 'paid'
),
first_two AS (
    SELECT
        user_id,
        MAX(order_at) FILTER (WHERE rn = 1) AS order1,
        MAX(order_at) FILTER (WHERE rn = 2) AS order2
    FROM ordered
    WHERE rn <= 2
    GROUP BY user_id
)
SELECT
    PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (order2 - order1)) / 86400) AS median_days,
    AVG(EXTRACT(EPOCH FROM (order2 - order1)) / 86400) AS avg_days
FROM first_two
WHERE order2 IS NOT NULL;

Считаем и медиану, и среднее: распределение времени до второй покупки обычно скошено (часть клиентов возвращается сразу, часть — спустя месяцы), поэтому медиана надёжнее среднего.

Закрепи формулу repeat buyer rate в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать repeat buyer rate в Telegram

По каналам привлечения

Разбивка по каналу показывает, откуда приходят лояльные покупатели, а не разовые «охотники за скидкой»:

SELECT
    u.acquisition_channel,
    COUNT(DISTINCT u.user_id) AS customers,
    COUNT(DISTINCT u.user_id) FILTER (
        WHERE EXISTS (
            SELECT 1 FROM orders o
            WHERE o.user_id = u.user_id
              AND o.status = 'paid'
            GROUP BY o.user_id
            HAVING COUNT(*) >= 2
        )
    ) AS repeat_buyers,
    COUNT(DISTINCT u.user_id) FILTER (
        WHERE EXISTS (
            SELECT 1 FROM orders o
            WHERE o.user_id = u.user_id
              AND o.status = 'paid'
            GROUP BY o.user_id
            HAVING COUNT(*) >= 2
        )
    )::NUMERIC * 100 / COUNT(DISTINCT u.user_id) AS repeat_rate
FROM users u
WHERE u.acquired_at >= CURRENT_DATE - INTERVAL '12 months'
GROUP BY u.acquisition_channel
ORDER BY repeat_rate DESC;

Такой разрез часто важнее среднего числа: канал с дешёвым привлечением, но нулевым повтором проигрывает более дорогому каналу с высоким repeat rate — по LTV, а не по цене клика.

Как это спрашивают на собесе

Метрику любят на собесах в e-commerce и retail — она проверяет и SQL, и понимание, что повтор ≠ retention.

«Чем repeat buyer rate отличается от retention?» Retention обычно про удержание по периодам (вернулся ли пользователь в месяц N), а repeat buyer rate — про сам факт повторной покупки за окно. Это близкие, но разные метрики, и путать их на собесе — минус.

«Почему свежая когорта показывает низкий repeat rate?» Потому что новым покупателям физически не хватило времени на вторую покупку. Поэтому метрику считают по когортам с равным окном и отрезают когорты, у которых окно ещё не закрылось. Разобрать такие продуктовые кейсы с решением можно в Карьернике.

«Как выбрать окно — 90 дней, 12 месяцев, lifetime?» Зависит от цикла покупки: для товаров с частым потреблением подойдёт короткое окно, для дорогих редких покупок — длинное. Главное — зафиксировать окно и не сравнивать метрики, посчитанные на разных окнах.

«Считать ли возвраты?» Заказ, который потом вернули, обычно исключают: это не удержанный клиент, а несостоявшаяся покупка. Иначе метрика завышается.

Частые ошибки

  • Свежие покупатели занижают метрику. Когорта, привлечённая месяц назад, показывает низкий repeat rate просто потому, что не успела купить второй раз. Считайте по когортам с равным окном.
  • Не учитывать возвраты. Заказ вернули — клиента нельзя считать повторным покупателем. Возвраты надо исключать, иначе метрика завышается.
  • Смешивать разные окна. 12 месяцев и lifetime дают разные цифры. Сравнивать их между собой нельзя — фиксируйте одно окно для всех расчётов.
  • Размытое определение «повтора». 2+ заказа или 3+? Второй заказ в течение 30 дней или когда угодно? От определения зависит цифра, поэтому его надо зафиксировать явно.
  • Дубли из-за нескольких аккаунтов. Один человек с двумя аккаунтами выглядит как два разных «разовых» покупателя. Без склейки идентичности (identity resolution) метрика занижается.

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

FAQ

Какой Repeat Buyer Rate считается нормальным?

Ориентиры сильно зависят от категории: для среднего e-commerce это примерно 20–30%, для подписок и товаров регулярного потребления — 40–60%, а лучшие в классе доходят до 70%+. Абсолютную цифру всегда сравнивают внутри своей категории, а не между разными типами бизнеса.

Repeat buyer и returning customer — это одно и то же?

Часто их используют как синонимы, но акцент разный: «repeat buyer» — про факт второй покупки после первой, «returning customer» — про возврат после периода неактивности. В конкретной компании стоит уточнить, что именно вкладывают в термин, чтобы считать одно и то же.

Какое окно выбрать — 30, 90 дней или lifetime?

Зависит от цикла покупки: для частого потребления берут короткое окно, для редких дорогих покупок — длинное или lifetime. 90 дней — распространённый компромисс. Главное — выбрать одно окно и последовательно им пользоваться, иначе метрики нельзя сравнивать.

Как повысить Repeat Buyer Rate?

Рабочие рычаги: email-реактивация и напоминания, программы лояльности, перевод на подписку для расходуемых товаров и снижение трения при повторной покупке (сохранённые карты, быстрый повторный заказ). Все они бьют в одно — упростить и мотивировать второй заказ.

Насколько повторные покупатели ценнее первичных?

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