Короткий ответ
Нужно соединить таблицу назначений в эксперимент с таблицей целевых событий через LEFT JOIN, сгруппировать по варианту и посчитать и общее число пользователей, и число совершивших целевое действие, чтобы конверсия (converted / total) и размер выборки были видны вместе.
Как это работает подробнее
Как это работает: LEFT JOIN от назначений к событиям гарантирует, что пользователи без целевого действия тоже учтутся (с NULL в поле события), и COUNT(DISTINCT CASE WHEN event_user_id IS NOT NULL THEN assignment_user_id END) корректно посчитает только тех, у кого нашлось событие, деля на общее COUNT(DISTINCT assignment_user_id).
Пример кода
PostgreSQL: конверсия A/B-теста
WITH converted AS (
SELECT DISTINCT a.variant, a.user_id
FROM experiment_assignments AS a
JOIN target_events AS e
ON e.user_id = a.user_id
AND e.event_time >= a.assigned_at
WHERE a.experiment_id = 'checkout_redesign'
)
SELECT a.variant,
COUNT(DISTINCT a.user_id) AS users_cnt,
COUNT(DISTINCT c.user_id) AS converted_cnt,
ROUND(100.0 * COUNT(DISTINCT c.user_id)
/ NULLIF(COUNT(DISTINCT a.user_id), 0), 2) AS conversion_pct
FROM experiment_assignments AS a
LEFT JOIN converted AS c
ON c.variant = a.variant AND c.user_id = a.user_id
WHERE a.experiment_id = 'checkout_redesign'
GROUP BY a.variant;Что использовать на практике
- На практике: важно всегда показывать рядом с конверсией размер выборки каждой группы — без этого «разница в конверсии 2 п.п.» невозможно правильно интерпретировать: на малой выборке это может быть шумом, на большой — значимым эффектом. SQL может посчитать сырые цифры, но решение о статистической значимости обычно требует дополнительного теста (например, z-теста для пропорций) за пределами SQL.
- Проверка: Проверка:
users_cntпо группам должен быть близок к ожидаемому размеру выборки, аconverted_cntне может превышатьusers_cnt.
Подводные камни
- Частые ошибки: используют
INNER JOINвместоLEFT JOINмежду назначением и событием, из-за чего пользователи без события выпадают из знаменателя, а не остаются там с нулевым числителем — это искусственно завышает конверсию для обеих групп.