Воронка с повторным входом — отнести каждого пользователя раз к его дальнему шагу в окне
Таблица events(user_id, event_type, event_time) со шагами view, cart, purchase. Пользователи входят в воронку повторно и повторяют шаги. За одно окно анализа отнесите каждого пользователя ровно раз — к самому дальнему достигнутому шагу — и выведите кумулятивную воронку (сколько дошли хотя бы до каждого шага).
-- каждый пользователь раз на своём дальнем шаге, кумулятивная воронка
Напишите запрос.
Ранжируют шаги (view=1, cart=2, purchase=3) и берут MAX(step_rank) на пользователя в окне — это схлопывает повторный вход в один дальний шаг. Затем считают через FILTER (WHERE max_step >= k) для каждого k — кумулятивная воронка, где каждый посчитан раз.
- ✗Считать, что distinct-на-шаг уже верно учитывает повторный вход
- ✗Брать хронологически последнее событие как дальний шаг
- ✗Суммировать ранги шагов, так что повторы обгоняют один глубокий проход
- →Почему обычная distinct-на-шаг воронка может дважды счесть вернувшегося?
- →Как ограничить дальний шаг одной сессией, а не всем окном?
Reduce each user to a single number — the rank of the furthest step they reached in the window — then build the cumulative funnel from that per-user maximum:
WITH furthest AS (
SELECT user_id,
MAX(CASE event_type
WHEN 'view' THEN 1
WHEN 'cart' THEN 2
WHEN 'purchase' THEN 3
END) AS max_step
FROM events
WHERE event_time >= DATE '2024-01-01'
AND event_time < DATE '2024-02-01'
GROUP BY user_id
)
SELECT
COUNT(*) FILTER (WHERE max_step >= 1) AS reached_view,
COUNT(*) FILTER (WHERE max_step >= 2) AS reached_cart,
COUNT(*) FILTER (WHERE max_step >= 3) AS reached_purchase
FROM furthest;
MAX(step_rank) per user is the crux: re-entries and repeated steps collapse into one furthest point, so a user who looped view→cart→view is still attributed once, at cart. The >= k filters make it cumulative and monotonic (reached_view >= reached_cart >= reached_purchase). A naive COUNT(DISTINCT user_id) per step can double-count intent and does not guarantee monotonicity when steps are skipped; taking the last event by time is wrong because the final logged step is often a backtrack, not the deepest one.