Как посчитать Net Dollar Retention в SQL
Содержание:
Зачем NDR
Net Dollar Retention (NDR, или NRR) — главная метрика SaaS. Показывает, как меняется выручка cohort'а заказчиков без учёта новых продаж. NDR > 100% — даже без new business cohort растёт. Под 100% — теряет. Хорошие public SaaS компании держат NDR 110-130%.
Формула
NDR = (start_MRR + expansion − contraction − churn) / start_MRRstart_MRR— MRR cohort'а на старте периодаexpansion— рост от upgrades, seat expansioncontraction— падение от downgradeschurn— полная потеря (cancellation)
NDR в SQL
Cohort = клиенты, активные на 1 января. Считаем NDR за 12 месяцев:
WITH start_cohort AS (
SELECT
customer_id,
mrr AS start_mrr
FROM subscription_state
WHERE state_date = '2025-05-01'
AND status = 'active'
),
end_state AS (
SELECT
customer_id,
mrr AS end_mrr
FROM subscription_state
WHERE state_date = '2026-05-01'
),
joined AS (
SELECT
s.customer_id,
s.start_mrr,
COALESCE(e.end_mrr, 0) AS end_mrr
FROM start_cohort s
LEFT JOIN end_state e USING (customer_id)
)
SELECT
SUM(start_mrr) AS total_start_mrr,
SUM(end_mrr) AS total_end_mrr,
SUM(end_mrr)::NUMERIC * 100 / NULLIF(SUM(start_mrr), 0) AS ndr_pct
FROM joined;end_mrr = 0 для churn'нувших — они вошли в cohort, но ушли.
NDR по cohort
Сравнение NDR по cohort'ам подписания:
WITH cohort AS (
SELECT
DATE_TRUNC('quarter', signup_date)::DATE AS cohort_quarter,
customer_id,
signup_mrr
FROM customers
WHERE signup_date BETWEEN '2024-01-01' AND '2025-04-01'
),
current_mrr AS (
SELECT customer_id, mrr AS current_mrr
FROM subscription_state
WHERE state_date = '2026-05-01'
)
SELECT
c.cohort_quarter,
COUNT(*) AS cohort_size,
SUM(c.signup_mrr) AS start_mrr,
SUM(COALESCE(cm.current_mrr, 0)) AS end_mrr,
SUM(COALESCE(cm.current_mrr, 0))::NUMERIC * 100 / NULLIF(SUM(c.signup_mrr), 0) AS ndr_pct
FROM cohort c
LEFT JOIN current_mrr cm USING (customer_id)
GROUP BY c.cohort_quarter
ORDER BY c.cohort_quarter;Если NDR падает по cohort'ам — продукт ухудшается для новичков.
NDR по сегментам
По плану / размеру клиента:
WITH start_state AS (
SELECT customer_id, plan_size, mrr
FROM subscription_state
WHERE state_date = '2025-05-01' AND status = 'active'
),
end_state AS (
SELECT customer_id, mrr AS end_mrr
FROM subscription_state
WHERE state_date = '2026-05-01'
)
SELECT
s.plan_size,
COUNT(*) AS cohort_size,
SUM(s.mrr)::NUMERIC AS start_mrr,
SUM(COALESCE(e.end_mrr, 0)) AS end_mrr,
SUM(COALESCE(e.end_mrr, 0))::NUMERIC * 100 / NULLIF(SUM(s.mrr), 0) AS ndr_pct
FROM start_state s
LEFT JOIN end_state e USING (customer_id)
GROUP BY s.plan_size
ORDER BY ndr_pct DESC;Enterprise обычно даёт NDR 130-150%, SMB — 90-110%.
Частые ошибки
Ошибка 1. Включать new business. NDR считают только на cohort'е, существовавшем на start. New customers — отдельная метрика.
Ошибка 2. Считать в headcount, не в dollars. Net Revenue Retention — про деньги, не про юзеров. 100 customers ушли по $10, 1 пришёл за $5000 — NDR может быть > 100%.
Ошибка 3. Не учитывать annual prepayments. Если клиент платит за год вперёд, MRR = annual / 12. Не вся annual ставится в одном месяце.
Ошибка 4. Игнорировать downgrades без cancellation. Customer на Premium перешёл на Basic — это contraction, не churn.
Ошибка 5. NDR на маленьких cohort'ах. < 30 customers → один whale меняет картину. Сегментация обязательна.
Связанные темы
- Как посчитать MRR в SQL
- Как посчитать NRR в SQL
- Как посчитать gross dollar retention в SQL
- Как посчитать expansion MRR в SQL
FAQ
NDR vs NRR?
Net Dollar Retention и Net Revenue Retention — одно и то же. Разные названия.
Какой NDR хороший?
Public SaaS медиана: 110-115%. Топ-компании: 130%+. SMB сегменты: 90-100%.
NDR может быть 0?
Если cohort полностью отвалился — да. Обычно cohort hits 80-90% retention floor.
NDR за месяц или за год?
Год — стандарт. За месяц — слишком волатильно.
NDR на startup без cohort?
Невозможно. Нужен period история. Альтернатива — gross churn rate.