Комментарии 2
Если нужны все клиенты, а из заказов — только оплаченные, условие можно перенести в
ON:
Если пишете "можно" - то показывайте и альтернативу. А заодно рассказывайте, в каком случае эти три варианта реализуют не две, а три разные логики.
Здравствуйте!
Спасибо, альтернативу действительно стоило показать. Для исходной задачи можно сначала отфильтровать заказы в подзапросе:
SELECT c.name, o.id AS order_id
FROM customers AS c
LEFT JOIN ( SELECT id, customer_id FROM orders WHERE status = 'paid'
) AS o ON o.customer_id = c.id;В данном запросе это эквивалентно условию o.status = 'paid' в ON: сохранятся все клиенты, а присоединятся только оплаченные заказы.
Третья логика получается, например, если после обычного соединения по customer_id написать WHERE o.status = 'paid' OR o.id IS NULL. Здесь предполагаем, что orders.id — первичный ключ и не допускает NULL.
На данных из поста все три варианта дадут разные результаты:
Фильтр оплаты в
ON: Анна с заказом №101, Борис и Вера сNULLвместо номера заказа.Фильтр оплаты в
WHERE: только Анна с заказом №101.Фильтр в
WHEREс добавлениемORo.idIS NULL: Анна с заказом №101 и Вера сNULL. Борис исчезнет.
У Бориса заказ нашёлся при соединении, поэтому строка с NULL для него не создаётся. Затем его неоплаченный заказ отбрасывает WHERE. У Веры заказов нет, поэтому созданная соединением строка с NULL проходит условие o.id IS NULL.
Получается, третий вариант сохраняет клиентов вообще без заказов, но исключает тех, у кого заказы есть и ни один не оплачен. Поэтому он не заменяет фильтрацию в ON для исходной задачи «сохранить всех клиентов». Стоило конкретно разобрать это в посте(
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Куда пропали клиенты без покупок? Ловушка WHERE после LEFT JOIN Нужно вывести всех клиентов и их оплаченные заказы....