Почините запрос воронки, показывающий больше покупок, чем добавлений в корзину
Отчёт показывает purchased больше, чем carted, что невозможно для упорядоченной воронки cart → purchase. Найдите причину и почините так, чтобы покупки были строгим подмножеством добавлений в корзину.
SELECT
(SELECT COUNT(DISTINCT user_id) FROM events WHERE event_name = 'cart') AS carted,
(SELECT COUNT(*) FROM events WHERE event_name = 'purchase') AS purchased;
Найдите и исправьте ошибку.
Две ошибки завышают purchased: он берёт COUNT(*), поэтому повторы считаются многократно, и считает всех покупателей — включая купивших через «Buy Now», не положив в корзину. Дедупят до уникальных пользователей и требуют, чтобы покупка шла за первым cart в окне. Тогда она — строгое подмножество carted.
- ✗Брать COUNT(*), из-за чего повторные покупки завышают шаг
- ✗Считать всех покупателей, включая тех, кто ни разу не клал в корзину
- ✗Считать, что покупка всегда подразумевает предшествующий по порядку cart
- →Почему прямые покупки «Buy Now» могут ломать монотонность воронки?
- →Как окно конверсии не пускает несвязанную позднюю покупку в счёт?
purchased climbs above carted for two reasons: COUNT(*) counts purchase rows (a user who bought twice is counted twice), and the purchase subquery is unconstrained — it credits everyone who ever purchased, including direct 'Buy Now' buyers who skipped the cart entirely. Reduce to one row per user, then require the purchase to follow that user's first cart within the window:
WITH steps AS (
SELECT
user_id,
MIN(event_time) FILTER (WHERE event_name = 'cart') AS t_cart,
MIN(event_time) FILTER (WHERE event_name = 'purchase') AS t_purchase
FROM events
GROUP BY user_id
)
SELECT
COUNT(*) FILTER (WHERE t_cart IS NOT NULL) AS carted,
COUNT(*) FILTER (
WHERE t_purchase > t_cart
AND t_purchase <= t_cart + INTERVAL '7 days'
) AS purchased
FROM steps;
Now purchased counts only users who carted first and then purchased within 7 days, so it is a strict subset of carted and can never exceed it. Note the subtlety: a genuine 'Buy Now' path that skips the cart is not a query bug — it means the funnel model itself is wrong, and that direct path should be modelled as its own entry rather than forced under cart → purchase.