После JOIN метрика стала завышенной, и аналитик добавил DISTINCT ко всей таблице, чтобы убрать дубли. Почему это рискованный подход?
ADISTINCT замедляет выполнение запроса и не даёт использовать индекс, из-за чего база переключается на full scan по таблицам
BDISTINCT удаляет строки без проверки внешних ключей, что может нарушить ссылочную целостность итогового набора данных
CDISTINCT маскирует причину раздувания строк после JOIN и может убрать настоящие повторы в данных, занижая метрику
DDISTINCT не работает с агрегатными функциями SUM и COUNT и поэтому не способен повлиять на завышенный результат метрики
Правильный ответ. DISTINCT поверх результата JOIN убирает симптом, а не причину — раздувание строк из-за связи многие-ко-многим. Корректный подход — дедуплицировать или агрегировать до соединения.
Разбор
После JOIN с дублированием строк DISTINCT может схлопнуть как лишние комбинации, так и легитимные повторы (например, два одинаковых товара в одном заказе), что искажает метрику в обе стороны. Главная проблема — потеря понимания, на каком уровне детализации (order, item, user) считается метрика. Правильный путь: pre-aggregate до уровня нужной сущности или явно выбрать ключ группировки и считать SUM/COUNT по нему. Производительность тут вторична.
Проверь себя · 1/3разбор после ответа
Вы считаете «уникальные покупатели по бренду». Данные:
order_items(user_id, product_id) и products(product_id, brand). Один пользователь может купить несколько товаров одного бренда. Какой расчёт на объединённых данных соответствует цели и устойчив к дублированию строк?Ещё вопросы по теме «JOIN и кардинальность»
- В таблице `users` 100 000 строк, в таблице `user_profiles` — ровно одна строка на каждого `user_id`. Вы делаете `INNER JOIN` по `user_id`. Что верно про число строк результата?
- Вы соединяете таблицы пользователей и заказов по `user_id`, где у одного пользователя может быть много заказов (связь «один ко многим»). Как посчитать число пользователей, которые сделали хотя бы один заказ, и не получить дубли?
- Для одного `order_id` в `order_items` есть 3 строки, а в `payments` — 2 строки. Вы соединили обе таблицы по `order_id` без предварительной агрегации. Сколько строк получится для этого заказа и почему?
- Нужен набор данных на уровне `user_id`: выручка из `orders` и число сессий из `sessions`. В обеих таблицах по пользователю много строк (один-ко-многим). Какой подход минимизирует риск размножения строк в соединении?
- Вы хотели посчитать средний чек по заказам как `AVG(order_total)`. Но перед этим соединили `orders` с `order_items` по `order_id` (связь один-ко-многим). Почему `AVG()` может измениться по сравнению с расчётом на таблице `orders`?
- Все вопросы по «JOIN и кардинальность» →