← Назад к вопросам
SQL: Найти пользователей с регулярными платежами
2.0 Middle🔥 181 комментариев
#SQL и базы данных#Метрики продукта
Условие
У вас есть таблица payments:
- payment_id (integer)
- user_id (integer)
- amount (decimal)
- payment_date (date)
Найдите пользователей, которые совершают платежи регулярно (каждую неделю в течение последнего месяца).
Ожидаемый результат:
Таблица с колонками: user_id, payments_count, weeks_with_payments, avg_payment
Источник: анализ подписочного поведения
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
Это задача на выявление регулярных плательщиков (recurring revenue users) — критична для MRR прогнозов в подписочных моделях.
Логика решения:
- Группируем платежи по пользователям и неделям — определяем, в какие недели платил пользователь
- Считаем количество недель с платежами — пользователь платил в 4 разные недели = регулярный
- Фильтруем по критериям — последний месяц, минимум 2+ недель
SQL запрос для выявления регулярных плательщиков:
WITH monthly_payments AS (
SELECT
user_id,
DATE_TRUNC('week', payment_date)::date as payment_week,
COUNT(*) as weekly_count,
SUM(amount) as weekly_amount
FROM payments
WHERE payment_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY user_id, DATE_TRUNC('week', payment_date)
),
user_regularity AS (
SELECT
user_id,
COUNT(DISTINCT payment_week) as weeks_with_payments,
COUNT(*) as total_payments,
SUM(weekly_amount) as total_amount,
ROUND(AVG(weekly_amount), 2) as avg_weekly_payment
FROM monthly_payments
GROUP BY user_id
)
SELECT
user_id,
weeks_with_payments,
total_payments,
total_amount,
avg_weekly_payment,
CASE
WHEN weeks_with_payments >= 4 THEN 'Very Regular (4+ weeks)'
WHEN weeks_with_payments = 3 THEN 'Regular (3 weeks)'
WHEN weeks_with_payments = 2 THEN 'Semi-Regular (2 weeks)'
ELSE 'Occasional'
END as regularity_segment
FROM user_regularity
WHERE weeks_with_payments >= 2
ORDER BY weeks_with_payments DESC, total_amount DESC;
Вариант с расширенным анализом (включая variance):
WITH week_stats AS (
SELECT
user_id,
DATE_TRUNC('week', payment_date)::date as payment_week,
SUM(amount) as weekly_total
FROM payments
WHERE payment_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY user_id, payment_week
),
user_patterns AS (
SELECT
user_id,
COUNT(DISTINCT payment_week) as weeks_with_payments,
COUNT(*) as total_payments,
SUM(weekly_total) as total_amount,
ROUND(AVG(weekly_total), 2) as avg_payment,
ROUND(100.0 * STDDEV(weekly_total) / AVG(weekly_total), 2) as payment_variance_pct
FROM week_stats
GROUP BY user_id
)
SELECT
user_id,
weeks_with_payments,
total_payments,
ROUND(total_amount, 2) as avg_payment,
COALESCE(payment_variance_pct, 0) as variance_pct,
CASE
WHEN weeks_with_payments >= 4 AND payment_variance_pct <= 25 THEN 'Highly Predictable'
WHEN weeks_with_payments >= 4 THEN 'Regular but Variable'
WHEN weeks_with_payments >= 3 THEN 'Semi-Regular'
ELSE 'Occasional'
END as segment
FROM user_patterns
WHERE weeks_with_payments >= 2
ORDER BY weeks_with_payments DESC, total_amount DESC;
Сравнение регулярных vs нерегулярных:
WITH user_patterns AS (
SELECT
user_id,
COUNT(DISTINCT DATE_TRUNC('week', payment_date)) as weeks_with_payments,
COUNT(*) as total_payments,
SUM(amount) as total_amount,
CASE WHEN COUNT(DISTINCT DATE_TRUNC('week', payment_date)) >= 4 THEN 'Regular' ELSE 'Irregular' END as user_type
FROM payments
WHERE payment_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY user_id
)
SELECT
user_type,
COUNT(*) as user_count,
ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER (), 2) as pct_of_users,
ROUND(AVG(total_amount), 2) as avg_ltv_30days,
SUM(total_amount) as total_revenue,
ROUND(100.0 * SUM(total_amount) / SUM(SUM(total_amount)) OVER (), 2) as pct_of_revenue
FROM user_patterns
GROUP BY user_type;
Прогноз MRR (Monthly Recurring Revenue):
WITH regular_users AS (
SELECT
user_id,
ROUND(AVG(amount), 2) as avg_weekly_payment
FROM payments
WHERE payment_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY user_id
HAVING COUNT(DISTINCT DATE_TRUNC('week', payment_date)) >= 4
)
SELECT
COUNT(*) as regular_users_count,
ROUND(SUM(avg_weekly_payment) * 4.33, 2) as projected_monthly_revenue
FROM regular_users;
Ожидаемый результат:
ОБЩАЯ СТАТИСТИКА:
Total Users Last 30 Days: 5,000
Regular Users (4+ weeks): 800 (16%)
Semi-Regular Users (2-3 weeks): 1,200 (24%)
Occasional Users: 3,000 (60%)
ПО РЕГУЛЯРНОСТИ:
user_id | weeks_with_payments | avg_payment | segment
1001 | 4 | $15.50 | Highly Predictable
1002 | 4 | $18.00 | Regular but Variable
1003 | 3 | $22.00 | Semi-Regular
СРАВНЕНИЕ:
user_type | user_count | avg_ltv_30days | pct_of_revenue
Regular | 800 | $310.00 | 68%
Irregular | 4,200 | $54.00 | 32%
Ключевые метрики:
Regularity (регулярность):
- Highly Predictable — платит каждую неделю, сумма стабильна (variance < 25%)
- Regular — платит 4+ недели, но суммы варьируют
- Semi-Regular — платит 2-3 недели
- Occasional — платит нерегулярно
Применение в бизнесе:
- MRR прогнозирование — Regular users дают стабильный доход
- Retention стратегия — Semi-Regular нужно привести в Regular
- LTV расчет — Regular users имеют 3-5x выше LTV
- Риск управление — Occasional users высокий риск отока