Как посчитать price elasticity в SQL

Закрепи формулу price elasticity в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать price elasticity в Telegram

Зачем price elasticity

Price elasticity (PE) — насколько падает спрос при росте цены. Если повысили цену на 10%, продажи упали на 15% — эластичность −1.5 (эластично, плохо для revenue). Если упали на 5% — −0.5 (неэластично, повышение даст рост revenue). Базовая метрика pricing-команды.

Формула

PE = (Δquantity / quantity) / (Δprice / price)

Или через логарифмы:

PE = ln(Q2 / Q1) / ln(P2 / P1)

Логарифмическая версия симметрична: PE(P1→P2) = PE(P2→P1).

Эластичность в SQL

Сравнение двух периодов с разными ценами:

WITH periods AS (
    SELECT
        product_id,
        DATE_TRUNC('month', sold_at)::DATE AS month,
        AVG(price) AS avg_price,
        COUNT(*) AS quantity
    FROM orders
    WHERE sold_at >= '2026-01-01'
    GROUP BY product_id, DATE_TRUNC('month', sold_at)
),
with_prev AS (
    SELECT
        product_id,
        month,
        avg_price,
        quantity,
        LAG(avg_price) OVER (PARTITION BY product_id ORDER BY month) AS prev_price,
        LAG(quantity)  OVER (PARTITION BY product_id ORDER BY month) AS prev_quantity
    FROM periods
)
SELECT
    product_id,
    month,
    avg_price,
    quantity,
    LN(quantity::NUMERIC / NULLIF(prev_quantity, 0))
    / NULLIF(LN(avg_price::NUMERIC / NULLIF(prev_price, 0)), 0) AS price_elasticity
FROM with_prev
WHERE prev_price IS NOT NULL
  AND ABS(avg_price - prev_price) / NULLIF(prev_price, 0) > 0.01  -- хотя бы 1% изменения
ORDER BY month;

ABS(...) > 0.01 отсекает периоды без значимого price change — иначе деление на тончайший знаменатель даст шум.

Эксперимент с ценами

A/B-test разных цен — самый чистый способ:

WITH variants AS (
    SELECT
        variant,
        AVG(price) AS avg_price,
        COUNT(*) FILTER (WHERE event = 'purchase') AS purchases,
        COUNT(*) FILTER (WHERE event = 'view') AS views,
        COUNT(*) FILTER (WHERE event = 'purchase')::NUMERIC
        / NULLIF(COUNT(*) FILTER (WHERE event = 'view'), 0) AS cr
    FROM pricing_experiment_events
    WHERE experiment_id = 'pricing_2026q2'
    GROUP BY variant
)
SELECT
    -- Pair A vs B
    (SELECT cr FROM variants WHERE variant = 'A') AS cr_a,
    (SELECT cr FROM variants WHERE variant = 'B') AS cr_b,
    (SELECT avg_price FROM variants WHERE variant = 'A') AS price_a,
    (SELECT avg_price FROM variants WHERE variant = 'B') AS price_b,
    LN((SELECT cr FROM variants WHERE variant = 'B')
        / NULLIF((SELECT cr FROM variants WHERE variant = 'A'), 0))
    / NULLIF(LN((SELECT avg_price FROM variants WHERE variant = 'B')
        / NULLIF((SELECT avg_price FROM variants WHERE variant = 'A'), 0)), 0) AS pe;

Лучше эксперимент через дискретное изменение цены — это даёт чистую elasticity.

Закрепи формулу price elasticity в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать price elasticity в Telegram

По сегменту

Enterprise vs SMB обычно разные:

SELECT
    customer_segment,
    AVG(price_elasticity) AS avg_pe,
    PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY price_elasticity) AS median_pe
FROM elasticity_per_period
WHERE price_elasticity BETWEEN -10 AND 10  -- отсечь outliers
GROUP BY customer_segment;

Enterprise PE обычно −0.3 до −0.7 (неэластично — нужны для работы). SMB −1.0 до −2.0 (эластично, легко уходят).

Частые ошибки

Ошибка 1. Игнорировать confounders. Зимняя распродажа → цена ↓ и quantity ↑ — но не из-за цены, а из-за сезона. Контролируйте период.

Ошибка 2. Считать elasticity per single observation. Нужны хотя бы 2 точки price/quantity. Без variance — нет elasticity.

Ошибка 3. Знак. Эластичность отрицательная для normal goods. Положительная — для Veblen goods (раритеты) или ошибка в данных.

Ошибка 4. Не контролировать на cohort. Новые vs существующие customers могут иметь разную elasticity. Cohort-aware расчёт.

Ошибка 5. Игнорировать competitor pricing. Если конкурент уронил цены, у вас quantity упал — не из-за вашей цены.

Связанные темы

FAQ

Какое значение PE «нормально»?

Для SaaS −0.5 до −1.5 типично. > −1 (по модулю) — неэластично, можно повышать.

Как делать pricing-эксперимент?

Случайных новых юзеров делите на разные цены. Существующих не трогать — повышение цен на текущую базу это отдельная задача со своими рисками.

Что если PE положительный?

Ошибка данных, Veblen good, или confounding period.

Elasticity и revenue?

При PE = −1 — revenue константен при изменении цены. PE > −1 (неэластично) — повышение цены растит revenue. PE < −1 — понижение цены растит revenue.

Cross-price elasticity?

Как продажи product A зависят от цены B. Substitutes — положительная PE, complements — отрицательная.