Разберите следующий SQL-кейс: "SELECT users.id, orders.id FROM users LEFT JOIN orders ON users.id = orders.user_id WHERE orders.status = 'paid';" — что непреднамеренно делает этот запрос и как его править для корректного результата

1 Янв в 09:51
22 +1
0
Ответы
1
Что непреднамеренно делает запрос
SELECT users.id, orders.id
FROM users
LEFT JOIN orders ON users.id = orders.user_id
WHERE orders.status = 'paid';
- Из‑за фильтра в WHERE строки, у которых нет совпадающего заказа, получают значения полей orders = NULL, и условие orders.status=′paid′orders.status = 'paid'orders.status=paid для них ложно (NULL ≠ 'paid'). Поэтому такие пользователи вычёркиваются — по сути LEFT JOIN превращается в INNER JOIN по этому условию.
Почему так происходит (коротко)
- JOIN выполняется первым, а WHERE фильтрует результат джойна. Условие на поля правой таблицы в WHERE удаляет строки с NULL.
Эквивалентная логика (в KaTeX)
\( \text{LEFT JOIN ... WHERE orders.status = 'paid'} \;\Longrightarrow\;
\text{INNER JOIN ON users.id = orders.user_id AND orders.status = 'paid'} \)
Как править в зависимости от цели
1) Если вы хотите получить всех пользователей и только их оплаченные заказы (в том числе пользователей без оплаченных заказов — с NULL в orders.id):
- Перенести условие в ON:
SELECT users.id, orders.id
FROM users
LEFT JOIN orders ON users.id = orders.user_id AND orders.status = 'paid';
2) Если вы хотите только пользователей, у которых есть оплаченные заказы (т.е. фактически INNER JOIN):
- Использовать INNER JOIN или оставить исходный WHERE:
SELECT users.id, orders.id
FROM users
INNER JOIN orders ON users.id = orders.user_id
WHERE orders.status = 'paid';
3) Альтернативный паттерн (реже нужен): вернуть пользователей с оплач. заказами и тех, у кого нет заказов вообще (но исключить тех, у кого есть только неоплаченные заказы):
SELECT users.id, orders.id
FROM users
LEFT JOIN orders ON users.id = orders.user_id
WHERE orders.status = 'paid' OR orders.id IS NULL;
Короткое резюме
- Перенесите фильтр по правой таблице в ON, если хотите сохранить семантику LEFT JOIN и показывать пользователей без подходящих заказов; оставьте WHERE (или используйте INNER JOIN), если хотите только строки с существующими оплач. заказами.
1 Янв в 10:00
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир