RFM-анализ на SQL

RFM — это сегментация клиентов по трём метрикам: Recency — как давно клиент совершал покупку/действие. Показывает, "жив" ли клиент. Frequency — как часто он покупает. Показывает уровень вовлечённости и лояльности. Monetary — сколько денег он приносит. Показывает ценность клиента.

Логика простая: клиенты, которые покупали недавно, часто и много — самые ценные, а те, кто давно не появлялся и покупал редко/мало — кандидаты на отток. На основе этого строят точечные маркетинговые действия: VIP-программы, реактивационные кампании, персональные предложения — вместо того чтобы обращаться со всей базой одинаково.

Ключевые нюансы

Метод разбиения на баллы. NTILE делит клиентов на равные по количеству группы — удобно, но если распределение сильно скошено (у многих бизнесов 80% выручки делают 5% клиентов), лучше задавать фиксированные пороги через CASE WHEN.

Направление скоринга.

Recency инвертируется — чем меньше дней прошло, тем выше балл. Frequency и Monetary — чем больше, тем выше балл. Легко ошибиться и перепутать сортировку.

Окно анализа.

Период в данных сильно влияет на результат — слишком короткое окно урезает Frequency, слишком длинное — тащит устаревшее поведение.

Что считать Monetary.

Депозиты/выручка/чистая прибыль — не одно и то же. Для бизнеса важнее не "оборот", а реальная маржинальность клиента.

Статичность.

Классический RFM — это снимок на момент расчёта, а не прогноз. Он не предсказывает будущее поведение, только описывает прошлое — поэтому его часто комбинируют с churn-моделями или LTV-прогнозами.

Присвоение сегментов через CASE в конце — это ручная бизнес-логика, пороги нужно подбирать под конкретную отрасль и объём базы, а не использовать универсальный шаблон.

Дальше — сам SQL-запрос, который считает метрики, переводит их в баллы и присваивает сегменты.

WITH customer_metrics AS (
    SELECT
        customer_id,
        DATE_PART('day', CURRENT_DATE - MAX(order_date)) AS recency_days,
        COUNT(DISTINCT order_id) AS frequency,
        SUM(order_amount) AS monetary
    FROM orders
    WHERE order_date >= CURRENT_DATE - INTERVAL '365 days'
    GROUP BY customer_id
),

rfm_scores AS (
    SELECT
        customer_id,
        recency_days,
        frequency,
        monetary,
        -- Чем меньше recency_days, тем выше балл (5 = купил недавно)
        NTILE(5) OVER (ORDER BY recency_days DESC) AS r_score,
        NTILE(5) OVER (ORDER BY frequency ASC) AS f_score,
        NTILE(5) OVER (ORDER BY monetary ASC) AS m_score
    FROM customer_metrics
),

rfm_segments AS (
    SELECT
        customer_id,
        recency_days,
        frequency,
        monetary,
        r_score,
        f_score,
        m_score,
        CONCAT(r_score, f_score, m_score) AS rfm_cell,
        (r_score + f_score + m_score) AS rfm_total
    FROM rfm_scores
)

SELECT
    customer_id,
    recency_days,
    frequency,
    monetary,
    r_score,
    f_score,
    m_score,
    rfm_cell,
    rfm_total,
    CASE
        WHEN r_score >= 4 AND f_score >= 4 AND m_score >= 4 THEN 'Champions'
        WHEN r_score >= 3 AND f_score >= 3 THEN 'Loyal Customers'
        WHEN r_score >= 4 AND f_score <= 2 THEN 'New Customers'
        WHEN r_score <= 2 AND f_score >= 3 THEN 'At Risk'
        WHEN r_score <= 2 AND f_score <= 2 AND m_score <= 2 THEN 'Lost'
        ELSE 'Others'
    END AS segment
FROM rfm_segments
ORDER BY rfm_total DESC;

Как это работает customer_metrics — считает базовые метрики для каждого клиента: сколько дней прошло с последнего заказа, сколько всего заказов и на какую сумму. rfm_scores — с помощью NTILE(5) разбивает клиентов на 5 равных групп (квинтилей) по каждой метрике, получая баллы от 1 до 5. rfm_segments — объединяет баллы в код ячейки (например, "555" — лучшие клиенты) и суммарный балл. Финальный запрос — присваивает понятные названия сегментов на основе баллов.

Где я использовал

Трэвел: для отелей и туристических агентств RFM анализирует актуальность (последнее пребывание), частоту (повторные визиты) и денежную ценность (расходы), помогая выявлять лояльных клиентов для специальных предложений и увеличивая количество повторных бронирований.

Электронная коммерция: RFM в электронной коммерции помогает выявлять ценных клиентов на основе недавних и частых покупок, сегментируя их для целевых акций, чтобы стимулировать повторные покупки и увеличивать продажи за счёт персонализированных предложений.