Как посчитать ARPU в SQL
ARPU и ARPPU — формулы
ARPU (Average Revenue Per User) — выручка на пользователя:
ARPU = Revenue / Total UsersARPPU (Average Revenue Per Paying User) — выручка на платящего:
ARPPU = Revenue / Paying UsersСвязь: ARPU = Paying Rate × ARPPU.
ARPU за месяц
SELECT
SUM(amount) AS revenue,
COUNT(DISTINCT u.user_id) AS total_users,
SUM(amount) / COUNT(DISTINCT u.user_id) AS arpu
FROM users u
LEFT JOIN orders o ON o.user_id = u.user_id
AND o.created_at >= '2026-04-01'
AND o.created_at < '2026-05-01';Важно: LEFT JOIN чтобы пользователи без заказов тоже попали в знаменатель.
ARPPU за месяц
SELECT
SUM(amount) AS revenue,
COUNT(DISTINCT user_id) AS paying_users,
SUM(amount) / COUNT(DISTINCT user_id) AS arppu
FROM orders
WHERE created_at >= '2026-04-01' AND created_at < '2026-05-01'
AND status = 'paid';Знаменатель — только платящие.
ARPU по месяцам
WITH monthly AS (
SELECT DATE_TRUNC('month', created_at)::DATE AS month,
SUM(amount) AS rev
FROM orders WHERE status = 'paid' GROUP BY 1
),
active AS (
SELECT DATE_TRUNC('month', created_at)::DATE AS month,
COUNT(DISTINCT user_id) AS users
FROM events WHERE event = 'app_open' GROUP BY 1
)
SELECT m.month, m.rev / a.users AS arpu
FROM monthly m JOIN active a USING (month)
ORDER BY m.month;Тренироваться на таких вопросах можно в Telegram-боте Карьерник — там 1500+ задач с реальных собесов с разборами.
Декомпозиция ARPU
WITH data AS (
SELECT DATE_TRUNC('month', dt)::DATE AS month,
COUNT(DISTINCT user_id) AS total,
COUNT(DISTINCT user_id) FILTER (WHERE paid) AS paying,
SUM(amount) FILTER (WHERE paid) AS revenue
FROM user_activity
GROUP BY 1
)
SELECT month,
revenue / total AS arpu,
paying::NUMERIC / total AS paying_rate,
revenue / NULLIF(paying, 0) AS arppu,
-- Проверка: arpu = paying_rate × arppu
paying::NUMERIC / total * revenue / NULLIF(paying, 0) AS arpu_check
FROM data;Полезно видеть ARPU, Paying Rate, ARPPU одновременно для диагностики.
ARPU по сегментам
По каналам
SELECT u.channel,
SUM(o.amount) / COUNT(DISTINCT u.user_id) AS arpu
FROM users u
LEFT JOIN orders o ON o.user_id = u.user_id
AND o.created_at >= '2026-04-01'
AND o.created_at < '2026-05-01'
WHERE u.registered_at < '2026-04-01' -- активные до начала периода
GROUP BY u.channel;По платформе
SELECT platform, SUM(amount) / COUNT(DISTINCT user_id) AS arpu
FROM orders JOIN users USING (user_id)
WHERE created_at >= '2026-04-01' AND created_at < '2026-05-01'
GROUP BY platform;По когорте
WITH cohort AS (
SELECT user_id, DATE_TRUNC('month', MIN(created_at))::DATE AS cohort_month
FROM orders GROUP BY user_id
)
SELECT c.cohort_month,
SUM(o.amount) / COUNT(DISTINCT c.user_id) AS arpu_total
FROM cohort c
LEFT JOIN orders o USING (user_id)
GROUP BY c.cohort_month
ORDER BY c.cohort_month;MoM ARPU
WITH monthly_arpu AS (
SELECT DATE_TRUNC('month', o.created_at)::DATE AS month,
SUM(o.amount) / COUNT(DISTINCT u.user_id) AS arpu
FROM orders o
JOIN users u USING (user_id)
GROUP BY 1
)
SELECT month, arpu,
LAG(arpu) OVER (ORDER BY month) AS prev_arpu,
ROUND(100.0 * (arpu - LAG(arpu) OVER (ORDER BY month)) /
LAG(arpu) OVER (ORDER BY month), 2) AS mom_pct
FROM monthly_arpu
ORDER BY month;Ловушки
1. ARPU или ARPPU — зависит от задачи
- Для инвесторов: ARPU (total picture).
- Для продукта: ARPPU + Paying Rate (детализация).
2. «Активный» пользователь
Что именно в знаменателе ARPU:
- Все зарегистрированные?
- DAU за период?
- MAU за период?
Каждое определение даёт разный ARPU. Фиксируйте.
3. Mix-эффект
ARPU может упасть даже при стабильных сегментах — если изменился mix трафика. Смотрите кейс.
4. Free + paid пользователи
ARPU среди всех vs только активных — разные числа.
5. Refund не учтён
-- ❌ ARPU завышен
SUM(amount)
-- ✅ Net ARPU
SUM(amount - COALESCE(refund, 0))Нормы ARPU по индустриям (2026, РФ)
- Мобильные игры: $1–3 monthly.
- SaaS B2C: 200–2000₽/месяц.
- E-commerce: зависит от категории, обычно 3000–15000₽.
- SaaS B2B: $50–5000/месяц.
К слову, набить руку на таких кейсах удобно через тренажёр в Telegram — разбирайте по 10 вопросов в день, через 2 недели тема становится рефлексом.
ARPU в Python
import pandas as pd
revenue = orders[orders['status'] == 'paid']['amount'].sum()
total_users = users['user_id'].nunique()
arpu = revenue / total_usersARPU vs LTV
ARPU = выручка / пользователь за период (месяц).
LTV = ARPU × expected_lifetime = ARPU / churn_rate.ARPU — текущий момент. LTV — долгосрочная ценность.
Читайте также
FAQ
ARPU или ARPPU — что показывать PM?
Оба. ARPU для общей картины, ARPPU для оптимизации продаж премиум-тарифов.
Как считать ARPU с разовыми покупками?
Revenue за период / количество пользователей за тот же период. Пользователь, купивший несколько раз, учитывается один раз в знаменателе.
ARPU растёт при падении orders — хорошо?
Не всегда. Если активные пользователи платят больше — да. Если просто ушла аудитория с малыми чеками — спорно, проверьте total revenue.
Какое ARPU у Яндекса?
Разные продукты — разное ARPU. Яндекс Плюс — около 300₽/месяц, Такси — зависит от частоты, e-commerce — существенно выше.