Как посчитать Frequency в SQL
HAVING в SQL-запросе с группировкой?Содержание:
Зачем Frequency
Продакт смотрит retention 35% — кажется хорошо. Аналитик добавляет покупательскую frequency: повторные покупатели делают в среднем 1,8 покупок за квартал. Конкурент в той же категории — 4,2. Значит, пользователь возвращается, но мало покупает. CAC окупается медленно.
Frequency идёт в паре с retention: одна показывает «вернулся», вторая — «насколько активно». В RFM-анализе frequency определяет ценность сегмента. В статье — SQL для расчёта и подводные камни.
Что такое Frequency
Purchase Frequency — среднее число покупок одного пользователя за период.
Frequency = Total orders / Unique buyers (за период)В RFM F — это позиция пользователя в распределении frequency, обычно через NTILE(5).
Базовый расчёт
Данные: orders(user_id, order_id, total, status, created_at).
SELECT
COUNT(*) AS total_orders,
COUNT(DISTINCT user_id) AS unique_buyers,
COUNT(*)::NUMERIC / NULLIF(COUNT(DISTINCT user_id), 0) AS avg_frequency
FROM orders
WHERE status = 'paid'
AND created_at >= '2026-01-01'
AND created_at < '2026-04-01';Важно: делите заказы на уникальных покупателей (тех, кто хоть раз купил), а не на всех пользователей (которые могли не покупать). Иначе frequency занижено.
Frequency в RFM
WITH user_frequency AS (
SELECT
user_id,
COUNT(*) AS purchases,
MAX(created_at) AS last_purchase,
SUM(total) AS monetary
FROM orders
WHERE status = 'paid'
AND created_at >= CURRENT_DATE - INTERVAL '365 days'
GROUP BY user_id
)
SELECT
user_id,
purchases AS frequency,
EXTRACT(DAY FROM CURRENT_DATE - last_purchase) AS recency_days,
monetary,
NTILE(5) OVER (ORDER BY purchases DESC) AS f_score,
NTILE(5) OVER (ORDER BY last_purchase DESC) AS r_score,
NTILE(5) OVER (ORDER BY monetary DESC) AS m_score
FROM user_frequency;NTILE(5) делит пользователей на 5 квинтилей. F=1 — топ 20% по частоте.
Frequency по сегментам
По каналу привлечения
WITH user_freq AS (
SELECT
o.user_id,
u.acquisition_channel,
COUNT(*) AS purchases
FROM orders o
JOIN users u ON u.user_id = o.user_id
WHERE o.status = 'paid'
AND o.created_at >= CURRENT_DATE - INTERVAL '90 days'
GROUP BY o.user_id, u.acquisition_channel
)
SELECT
acquisition_channel,
COUNT(*) AS buyers,
AVG(purchases) AS avg_frequency,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY purchases) AS median_frequency
FROM user_freq
GROUP BY acquisition_channel
ORDER BY avg_frequency DESC;Медиана важна: канал с одним «китом» (10 покупок) и 9 случайными (1 покупка) даст среднее 1,9, но медиану 1.
Распределение frequency
WITH user_freq AS (
SELECT user_id, COUNT(*) AS purchases
FROM orders
WHERE status = 'paid' AND created_at >= CURRENT_DATE - INTERVAL '90 days'
GROUP BY user_id
)
SELECT
purchases,
COUNT(*) AS users,
COUNT(*) * 100.0 / SUM(COUNT(*)) OVER () AS pct
FROM user_freq
GROUP BY purchases
ORDER BY purchases;В e-com обычно 60-70% — 1 покупка, 15-20% — 2-3, остальные — 4+. «Хвост» из активных — самые ценные.
Visit Frequency vs Purchase Frequency
| Метрика | Что считаем |
|---|---|
| Visit Frequency | Кол-во сессий на пользователя |
| Purchase Frequency | Кол-во покупок на покупателя |
Visit frequency обычно в 5-15 раз выше purchase frequency. Конверсия ≈ purchase frequency / visit frequency × число посетителей.
WITH sessions_per_user AS (
SELECT user_id, COUNT(DISTINCT session_id) AS visits
FROM events
WHERE event_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY user_id
),
purchases_per_user AS (
SELECT user_id, COUNT(*) AS purchases
FROM orders
WHERE status = 'paid' AND created_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY user_id
)
SELECT
AVG(s.visits) AS avg_visit_freq,
AVG(p.purchases) AS avg_purchase_freq,
AVG(p.purchases)::NUMERIC / NULLIF(AVG(s.visits), 0) AS visit_to_purchase_ratio
FROM sessions_per_user s
LEFT JOIN purchases_per_user p ON p.user_id = s.user_id;Частые ошибки
Ошибка 1. Делить заказы на всех пользователей
COUNT(orders) / COUNT(DISTINCT users) где users — все зарегистрированные. Получите frequency 0,2 — но это не frequency, а конверсия × frequency. Делите только на тех, кто купил.
Ошибка 2. Не отсекать неоплаченные и отменённые заказы
Корзины и отменённые заказы не должны идти в frequency. Только status = 'paid' или 'delivered'.
Ошибка 3. Frequency на коротком периоде
7 дней → почти все пользователи с frequency = 1. Нужно ≥ 30-90 дней для содержательных значений.
Ошибка 4. Среднее вместо медианы
Один «кит» с 50 покупками сдвигает среднее на 30%. Показывайте медиану рядом или используйте NTILE / перцентили.
Ошибка 5. Frequency без сегментации
Общая frequency 1,9 говорит мало. Frequency по сегментам (B2B и B2C, когорта повторных покупателей, регион) показывает реальную динамику.
Ошибка 6. Путать с frequency cap в маркетинге
В рекламе «frequency cap» — это другое понятие (макс. показов на пользователя). В аналитике frequency — про действия пользователя.
Связанные темы
FAQ
Какая frequency считается хорошей?
Всё зависит от категории. В FMCG это 4–8 покупок в месяц, в одежде — 1–3 за квартал, в электронике — 0,3–0,8 в год, в доставке еды — 5–15 в месяц. Ориентир один: сравнивайте себя с конкурентами в своей категории, а не с абсолютными цифрами.
Frequency или Retention — что показывать?
Retention показывает, вернулся ли пользователь, а frequency — насколько активно он покупает после возврата. Показывать лучше обе метрики вместе: retention 35% при frequency 2 — это лоялисты, а те же 35% при frequency 1,1 — «зомби-аккаунты», которые заходят, но почти не покупают.
Frequency считать по календарю или по возрасту когорты?
Зависит от вопроса. Календарное окно (последние 90 дней) подходит для оперативного отчёта. Возраст когорты (первые 90 дней после регистрации) нужен, когда вы анализируете онбординг и хотите сравнить когорты между собой.
Что делать, если frequency низкая?
Начните с декомпозиции. Проверьте барьеры (нет нужного товара, слабый ассортимент), цены (дороже конкурентов), удержание (пользователи не возвращаются) и product-market fit. Из рычагов чаще всего помогают cross-sell, программа лояльности и пуши на возврат.
Как считать frequency для подписочного бизнеса?
В подписке frequency обычно не используют — там смотрят на active months или на отток. Frequency уместен для транзакционного бизнеса с отдельными разовыми покупками, а не с регулярными списаниями.