Можно ли из left join сделать right join, если база не поддерживает right join
Что проверяют
Понимаете ли вы, что RIGHT JOIN это тот же LEFT JOIN, только с таблицами в другом порядке. Для тестировщика это рабочий навык: проверочные запросы приходится писать в разных СУБД, и не везде есть все виды соединений. Следом часто просят найти записи без пары или собрать FULL OUTER JOIN там, где его нет.
Как отвечать
Да, любой RIGHT JOIN переписывается через LEFT JOIN перестановкой таблиц. Запрос SELECT o.id, c.name FROM orders o RIGHT JOIN customers c ON c.id = o.customer_id равносилен запросу SELECT o.id, c.name FROM customers c LEFT JOIN orders o ON c.id = o.customer_id.
В обоих случаях возвращаются все клиенты, а у клиентов без заказов поля заказа будут NULL. Условие в ON не меняется, меняется только то, какая таблица стоит слева.
Что стоит добавить:
- порядок колонок: при
SELECT *он поменяется вместе с порядком таблиц. Если результат сравнивают построчно, перечисляйте колонки явно; - поддержка: SQLite не умел
RIGHT JOINиFULL OUTER JOINдо версии 3.39, и старые сборки, например встроенные в старые версии мобильных ОС, до сих пор встречаются. В MySQL нетFULL OUTER JOIN; - эмуляция FULL OUTER:
A LEFT JOIN B, затемUNION ALLсB LEFT JOIN A ... WHERE a.id IS NULL, чтобы не задвоить совпавшие строки; - поиск сирот:
LEFT JOIN ... WHERE b.id IS NULLнаходит записи без пары, типичная проверка целостности после миграции данных.
Где спотыкаются
Ставят фильтр по присоединяемой таблице в WHERE. Условие WHERE o.status = 'paid' отбрасывает строки с NULL и превращает внешнее соединение во внутреннее. Если нужны все клиенты, такой фильтр кладут в ON.
Эмулируют FULL OUTER JOIN через простой UNION. Он схлопывает дубликаты, в том числе настоящие одинаковые строки, и результат расходится с оригиналом.
Переписывают цепочку из трёх и более соединений механически. Когда RIGHT JOIN стоит в середине, простой перестановки двух таблиц мало: нужно заново выстроить порядок соединений и проверить результат на данных с пропусками.