Привет! На связи Вячеслав Потапов, ментор курса «Аналитик данных» 👋🏻
Предыдущий пост набрал много реакций, а значит, тема вам интересна) Расскажу про ещё одну типовую ошибку, из-за которой начинающие аналитики дают неправильные результаты.
Предположим, у нас есть две таблицы:
users
user_id registration_date
1 2024-01-01
2 2024-01-03
3 2024-01-05
orders
order_id user_id order_date
101 1 2024-01-10
102 1 2024-01-15
103 2 2024-01-20
Задача: посчитать всех пользователей и количество их заказов. Даже если заказов нет, то пользователь всё равно должен попасть в результат.
Новички часто пишут так:
select
u.user_id,
count(o.order_id) as orders_cnt
from users u
left join orders o
on u.user_id = o.user_id
where o.order_date >= '2024-01-01'
group by u.user_id;
И пользователь
user_id = 3 пропадает из результатов.Почему так происходит?
Ключевой момент, который часто не понимают —
WHERE применяется после JOIN.Для пользователя без заказов:
🟠
o.order_date = NULL;🟠 Условие
o.order_date >= '2024-01-01' возвращает NULL;🟠
WHERE оставляет только TRUE.В итоге
LEFT JOIN превращается в INNER JOIN, и все пользователи без заказов вылетают из результата. SQL отработал корректно, а ошибка в логике запроса.Как правильно?
Есть несколько безопасных способов.
#️⃣ Способ 1. Перенести условие в JOIN. Самый частый и правильный вариант:
select
u.user_id,
count(o.order_id) as orders_cnt
from users u
left join orders o
on u.user_id = o.user_id
and o.order_date >= '2024-01-01'
group by u.user_id;
Теперь пользователи без заказов остаются, и
count() корректно вернёт 0.#️⃣ Способ 2. Явно учесть NULL:
where o.order_date >= '2024-01-01'
or o.order_date is null
Работает, но читаемость хуже, и легко допустить ошибку.
#️⃣ Способ 3. Агрегация до JOIN. Самый надёжный подход, особенно для больших объёмов данных:
with orders_cnt as (
select user_id, count(*) as cnt
from orders
where order_date >= '2024-01-01'
group by user_id
)
select
u.user_id,
coalesce(o.cnt, 0) as orders_cnt
from users u
left join orders_cnt o using(user_id);
50 реакций — и сделаем ещё один такой разбор ошибки 🧡
📊 Simulative