Короткий ответ
При LEFT JOIN условие в ON определяет, какие правые строки можно присоединить, но не удаляет строку слева. Фильтр в WHERE применяется к уже соединённому результату и может исключить строку с NULL справа.
Как это работает подробнее
Если оплаченного заказа нет, соединение с условием o.status = 'paid' в ON всё равно вернёт клиента, а поля заказа будут NULL. При таком же условии в WHERE выражение для этого клиента станет неизвестным, и строка исчезнет.
Исключение возможно, если фильтр WHERE явно сохраняет отсутствующую правую часть, например WHERE o.status = 'paid' OR o.order_id IS NULL, но условие в ON обычно выражает намерение яснее.
Пример кода
query.sql
SELECT c.customer_id, o.order_id
FROM customers AS c
LEFT JOIN orders AS o
ON o.customer_id = c.customer_id
AND o.status = 'paid'
ORDER BY c.customer_id, o.order_id;Что использовать на практике
- Фильтруйте правые совпадения в ON. Это сохраняет все объекты левой таблицы.
- Фильтруйте итоговый набор в WHERE. Делайте так только когда действительно хотите исключить часть строк после соединения.
Подводные камни
- Скрытый INNER JOIN. Условие
WHERE o.status = 'paid'удалит клиентов без подходящего заказа. - Проверка по nullable-полю. Для факта отсутствия связи лучше использовать ненулевой ключ правой таблицы.