Вы строите выручку по каналу: соединяете sessions(user_id, channel) и orders(user_id, revenue) по user_id, затем считаете SUM(revenue) по channel. Получившаяся выручка сильно больше бухгалтерской. Что наиболее вероятно и что делать?
AЗаменить
SUM(revenue) на AVG(revenue) — это скорректирует дублирование по сессиямBДобавить
SELECT DISTINCT на весь результирующий набор и пересчитать выручкуCИспользовать
COUNT(*) вместо SUM(revenue), так проблема дублирования исчезнетDЭто
many-to-many и join explosion: у пользователя много сессий и заказов, поэтому revenue дублируется; нужно pre-aggregate или строить атрибуцию по более точному ключу, чтобы избежать duplicationПравильный ответ. Соединение двух
one-to-many источников по user_id даёт many-to-many и ломает денежные метрики из-за duplication.Разбор
Каждый заказ пользователя матчится на каждую его сессию, поэтому один и тот же revenue учитывается много раз в SUM(). distinct может случайно скрыть часть дублей и сломать данные по-другому, поэтому это плохой костыль. Правильный путь — определить целевой уровень данных, pre-aggregate до него и затем соединять.
Проверь себя · 1/3разбор после ответа
Вы считаете «уникальные покупатели по бренду». Данные:
order_items(user_id, product_id) и products(product_id, brand). Пользователь может купить несколько товаров одного бренда. Какой расчёт на объединённых данных соответствует цели и устойчив к duplication?Ещё вопросы по теме «JOIN и кардинальность»
- В таблице `users` 100 000 строк, в таблице `user_profiles` — ровно одна строка на каждого `user_id`. Вы делаете `INNER JOIN` по `user_id`. Что верно про число строк результата?
- Вы соединяете `users` и `orders` по `user_id`, где у пользователя может быть много заказов (`one-to-many`). Как посчитать число пользователей, которые сделали хотя бы один заказ, чтобы избежать `duplication`?
- Для одного `order_id` в `order_items` есть 3 строки, а в `payments` есть 2 строки. Вы соединили всё в одну таблицу по `order_id` без предварительной агрегации. Сколько строк получится для этого заказа и почему?
- Нужен датасет на уровне `user_id`: выручка из `orders` и число сессий из `sessions`. В обеих таблицах по пользователю много строк (`one-to-many`). Какой подход минимизирует риск `join explosion`?
- Вы хотели посчитать средний чек по заказам как `AVG(order_total)`. Но перед этим соединили `orders` с `order_items` по `order_id` (`one-to-many`). Почему `AVG()` может измениться по сравнению с расчётом на таблице `orders`?
- Все вопросы по «JOIN и кардинальность» →