Трёхшаговая воронка — пользователи на каждом шаге и пошаговая конверсия
Таблица events(user_id, step) фиксирует шаги воронки, где step — это view, cart или purchase. Верните число уникальных пользователей на каждом шаге и две пошаговые конверсии — view→cart и cart→purchase — в процентах.
-- пользователи на шаг плюс конверсии view->cart и cart->purchase
Напишите запрос.
Считают уникальных пользователей на шаг условной агрегацией — COUNT(DISTINCT user_id) FILTER (WHERE step = 'view') и так же для cart и purchase. Каждая конверсия делит пользователей следующего шага на предыдущий: cart на view, purchase на cart — не на общий итог.
- ✗Делить каждый шаг на всю базу, а не на предыдущий шаг
- ✗Брать строки COUNT(*) вместо COUNT(DISTINCT user_id)
- ✗Путать пошаговую конверсию со сквозной
- →Как ещё вывести сквозную конверсию view→purchase?
- →Почему FILTER лучше трёх отдельных сгруппированных подзапросов?
Use conditional aggregation to count distinct users per step in one pass, then express each conversion relative to the previous step:
SELECT
COUNT(DISTINCT user_id) FILTER (WHERE step = 'view') AS viewed,
COUNT(DISTINCT user_id) FILTER (WHERE step = 'cart') AS carted,
COUNT(DISTINCT user_id) FILTER (WHERE step = 'purchase') AS purchased,
ROUND(100.0 * COUNT(DISTINCT user_id) FILTER (WHERE step = 'cart')
/ COUNT(DISTINCT user_id) FILTER (WHERE step = 'view'), 2) AS view_to_cart_pct,
ROUND(100.0 * COUNT(DISTINCT user_id) FILTER (WHERE step = 'purchase')
/ COUNT(DISTINCT user_id) FILTER (WHERE step = 'cart'), 2) AS cart_to_purchase_pct
FROM events
WHERE step IN ('view', 'cart', 'purchase');
COUNT(DISTINCT user_id) (not COUNT(*)) is essential — a user can log the same step twice. Step-to-step conversion divides adjacent steps; dividing by the total base would answer a different question. This "wide" funnel counts anyone who reached a step regardless of order; enforcing the view→cart→purchase order and a time window is a separate, harder query.