Как посчитать Uplift в SQL
created_at имеет тип timestamp. Какой тип данных вернёт DATE_TRUNC('day', created_at)?Содержание:
Зачем Uplift
В A/B-тесте тестовая группа (treatment) показала CR 5%, контрольная (control) — 4%. Uplift = +1 п.п. (абсолютный) или +25% (относительный). Какую цифру показывать команде? Зависит от контекста.
Uplift — основной способ выразить разницу в A/B. В статье — SQL и нюансы.
Абсолютный и относительный uplift
Absolute Uplift = CR_treatment - CR_control
Relative Uplift = (CR_treatment - CR_control) / CR_control × 100%Пример: CR контрольной группы 2%, тестовой 3%.
- Абсолютный: +1 п.п.
- Относительный: +50%
Относительный uplift выглядит больше, но обманчив на низких базах. Используйте оба.
Базовый расчёт
Данные: ab_assignments(user_id, group_name, exp_id), events(user_id, event_type).
WITH stats AS (
SELECT
a.group_name,
COUNT(DISTINCT a.user_id) AS users,
COUNT(DISTINCT CASE WHEN e.event_type = 'purchase' THEN a.user_id END) AS conversions
FROM ab_assignments a
LEFT JOIN events e ON e.user_id = a.user_id
WHERE a.exp_id = 'check_out_v2'
GROUP BY a.group_name
)
SELECT
group_name,
users,
conversions,
conversions::NUMERIC / NULLIF(users, 0) * 100 AS cr_pct
FROM stats;Затем для uplift:
WITH cr AS (
SELECT
group_name,
COUNT(DISTINCT CASE WHEN e.event_type = 'purchase' THEN a.user_id END)::NUMERIC
/ NULLIF(COUNT(DISTINCT a.user_id), 0) AS cr
FROM ab_assignments a
LEFT JOIN events e ON e.user_id = a.user_id
WHERE a.exp_id = 'check_out_v2'
GROUP BY a.group_name
)
SELECT
(SELECT cr FROM cr WHERE group_name = 'treatment') - (SELECT cr FROM cr WHERE group_name = 'control') AS absolute_uplift,
((SELECT cr FROM cr WHERE group_name = 'treatment') / NULLIF((SELECT cr FROM cr WHERE group_name = 'control'), 0) - 1) * 100 AS relative_uplift_pct;Uplift по сегментам
WITH cr_seg AS (
SELECT
a.group_name,
u.platform,
COUNT(DISTINCT CASE WHEN e.event_type = 'purchase' THEN a.user_id END)::NUMERIC
/ NULLIF(COUNT(DISTINCT a.user_id), 0) AS cr
FROM ab_assignments a
JOIN users u ON u.user_id = a.user_id
LEFT JOIN events e ON e.user_id = a.user_id
WHERE a.exp_id = 'check_out_v2'
GROUP BY a.group_name, u.platform
)
SELECT
platform,
MAX(CASE WHEN group_name = 'control' THEN cr END) AS cr_control,
MAX(CASE WHEN group_name = 'treatment' THEN cr END) AS cr_treatment,
MAX(CASE WHEN group_name = 'treatment' THEN cr END)
- MAX(CASE WHEN group_name = 'control' THEN cr END) AS abs_uplift
FROM cr_seg
GROUP BY platform;Confidence interval
WITH stats AS (
SELECT
group_name,
COUNT(DISTINCT a.user_id) AS n,
COUNT(DISTINCT CASE WHEN e.event_type = 'purchase' THEN a.user_id END) AS k
FROM ab_assignments a
LEFT JOIN events e ON e.user_id = a.user_id
WHERE a.exp_id = 'check_out_v2'
GROUP BY a.group_name
)
SELECT
group_name,
n,
k,
k::NUMERIC / n AS p,
1.96 * SQRT(k::NUMERIC / n * (1 - k::NUMERIC / n) / n) AS ci_radius
FROM stats;95% CI для CR: p ± ci_radius. Если CI контрольной и тестовой групп не пересекаются — uplift статистически значим (грубое приближение вместо z-test).
Частые ошибки
Ошибка 1. Считать относительный uplift на низкой базе. CR 0,1% → 0,15% = +50% относительно. Звучит огромно, но в абсолюте это всего +0,05 п.п.
Ошибка 2. Считать без проверки значимости. Uplift 2% при n=100 — может быть шумом. Нужен p-value или CI.
Ошибка 3. Игнорировать SRM. Перед расчётом uplift проверьте соотношение групп: если control 48% / treatment 52% при целевом 50/50, эксперимент сломан.
Ошибка 4. Кумулятивный vs финальный uplift. В A/B uplift первой недели может отличаться от финального. Не вытаскивайте промежуточные результаты раньше времени.
Ошибка 5. Несколько метрик. Считаете uplift по CR, AOV и выручке сразу. Множественные сравнения → ложные срабатывания. Используйте поправку Bonferroni или sequential testing.
Ошибка 6. Отрицательный uplift. Тестовая группа работает хуже контрольной — это валидный результат, его нельзя игнорировать.
Связанные темы
FAQ
Абсолютный или относительный?
Абсолютный uplift показывают, когда база известна и важна сама величина в пунктах. Относительный берут, чтобы подчеркнуть масштаб роста, но на низких базах он обманчив.
Какой uplift считается большим?
Для конверсионных метрик относительный uplift +5–10% — это нормальный результат. Всё, что выше +20%, считается большим и нередко оказывается шумом.
Отрицательный uplift — что делать?
Не выкатывать тестовую версию в прод и разобраться, почему она проиграла контрольной. Отрицательный результат — это тоже полезный вывод.
Uplift зависит от MDE?
Да. Если реальный эффект меньше заложенного MDE, uplift утонет в шуме, и тест не сможет надёжно его поймать.
Можно ли считать uplift в SQL для долгосрочных эффектов?
Стандартным запросом — нет. Долгосрочные эффекты обычно измеряют через holdout.