Нужен набор данных на уровне user_id: выручка из orders и число сессий из sessions. В обеих таблицах по пользователю много строк (один-ко-многим). Какой подход минимизирует риск размножения строк в соединении?
AСделать
JOIN таблиц orders и sessions по user_id, а затем посчитать SUM(amount) и COUNT(*) поверх результатаBСделать
JOIN сырых таблиц по user_id, а потом применить DISTINCT ко всем колонкам результатаCУдалить все строки кроме первой в
orders для каждого пользователя, чтобы соединение стало один-к-одномуDСначала свернуть
orders до одной строки на user_id и отдельно свернуть sessions, затем соединить готовые агрегатыПравильный ответ. Для метрик на уровне пользователя сначала сворачивают источники до нужного уровня детализации, и только потом соединяют.
Разбор
Если соединить «сырые» orders и sessions, получится связь многие-ко-многим по user_id, и строки будут размножаться. В результате денежные и счётные метрики будут завышены. Предварительная агрегация до одной строки на пользователя сохраняет правильный уровень данных и делает соединение ближе к один-к-одному. DISTINCT поверх раздутого результата не восстанавливает корректные суммы, а удаление лишних строк искажает данные.
Проверь себя · 1/3разбор после ответа
После
JOIN таблиц users и events по user_id (связь один-ко-многим) вы хотите получить число пользователей, у которых был хотя бы один ивент. Какой расчёт даст корректное число?Ещё вопросы по теме «JOIN и кардинальность»
- В таблице `users` 100 000 строк, в таблице `user_profiles` — ровно одна строка на каждого `user_id`. Вы делаете `INNER JOIN` по `user_id`. Что верно про число строк результата?
- Вы соединяете таблицы пользователей и заказов по `user_id`, где у одного пользователя может быть много заказов (связь «один ко многим»). Как посчитать число пользователей, которые сделали хотя бы один заказ, и не получить дубли?
- Для одного `order_id` в `order_items` есть 3 строки, а в `payments` — 2 строки. Вы соединили обе таблицы по `order_id` без предварительной агрегации. Сколько строк получится для этого заказа и почему?
- Вы хотели посчитать средний чек по заказам как `AVG(order_total)`. Но перед этим соединили `orders` с `order_items` по `order_id` (связь один-ко-многим). Почему `AVG()` может измениться по сравнению с расчётом на таблице `orders`?
- В каком случае `SUM(order_amount)` после `JOIN` скорее всего останется корректным, без эффекта размножения строк?
- Все вопросы по «JOIN и кардинальность» →