TGViewer
Симулейтив Симулейтив @simulative_official · 7.46K subscribers
Post #2877 1.34K
Типовая ошибка джунов: LEFT JOIN+WHERE

Привет! На связи Вячеслав Потапов, ментор курса «Аналитик данных» 👋🏻

Предыдущий пост набрал много реакций, а значит, тема вам интересна) Расскажу про ещё одну типовую ошибку, из-за которой начинающие аналитики дают неправильные результаты.

Предположим, у нас есть две таблицы:

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
  • 🔥 78
  • ❤ 26
  • 👍 18
More from @simulative_official
  1. Oct 1, 2026Post #3592
  2. Sep 30, 2026💻💻💻💻💻 Откуда на самом деле берутся данные? На учебных задачах всё просто: тебе дают г…
  3. Sep 30, 2026⭐️ Топ метрик, которые должен уметь считать каждый аналитик Рекламные метрики — это не про…
  4. Sep 29, 2026⭐️ Уже сегодня: как ML-инженер учит компьютер находить смысл в тексте Сегодня покажем проф…
  5. Sep 28, 2026#проанализировали_и_поняли
  6. Sep 27, 2026💻💻💻💻💻 Как работает ML-инженер — на примере поиска похожих текстов Пользователь вводит…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →