LEFT JOIN vs INNER JOIN — в чём разница и когда что использовать
Коротко
INNER JOIN возвращает только строки, у которых есть совпадение в обеих таблицах. LEFT JOIN возвращает все строки из левой таблицы, а если совпадения в правой нет — подставляет NULL. Это фундаментальный вопрос на любом собеседовании аналитика.
Как работает INNER JOIN
INNER JOIN оставляет только те строки, где ключ соединения нашёлся в обеих таблицах. Если в одной из таблиц нет совпадения — строка выпадает из результата.
SELECT u.user_id, u.name, o.order_id
FROM users u
INNER JOIN orders o ON u.user_id = o.user_id;Результат: только пользователи, у которых есть хотя бы один заказ. Пользователи без заказов не попадут в выборку.
Как работает LEFT JOIN
LEFT JOIN сохраняет все строки из левой таблицы (той, что в FROM). Если совпадения в правой таблице нет, колонки правой таблицы заполняются NULL.
SELECT u.user_id, u.name, o.order_id
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id;Результат: все пользователи. У тех, кто сделал заказ — заполнен order_id. У остальных — NULL в колонке order_id.
Ключевые отличия
| INNER JOIN | LEFT JOIN | |
|---|---|---|
| Строки без совпадения | Отбрасываются | Сохраняются (с NULL) |
| Количество строк | Зависит от ключа (при дубликатах может быть больше обеих таблиц) | ≥ левой таблицы |
| Порядок таблиц важен | Нет | Да (левая сохраняется) |
| Производительность | Обычно быстрее | Чуть медленнее |
| Когда использовать | Нужны только совпадения | Нужны все записи из левой таблицы |
Практический пример
Допустим, у нас 5 пользователей и 3 заказа:
users:
| user_id | name |
|---|---|
| 1 | Анна |
| 2 | Борис |
| 3 | Вика |
| 4 | Глеб |
| 5 | Дина |
orders:
| order_id | user_id | amount |
|---|---|---|
| 101 | 1 | 500 |
| 102 | 1 | 300 |
| 103 | 3 | 700 |
INNER JOIN вернёт 3 строки: Анна (2 заказа) и Вика (1 заказ). Борис, Глеб и Дина не попадут — у них нет заказов.
LEFT JOIN вернёт 5+ строк: Анна (2 строки), Борис (NULL), Вика (1 строка), Глеб (NULL), Дина (NULL).
Классический паттерн: найти записи без совпадений
LEFT JOIN + WHERE IS NULL — стандартный способ найти строки, у которых нет пары в другой таблице:
-- Пользователи без заказов
SELECT u.user_id, u.name
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
WHERE o.user_id IS NULL;На собеседовании это один из самых частых вопросов. Альтернативы: NOT EXISTS и NOT IN, но LEFT JOIN + IS NULL часто самый читаемый и эффективный вариант.
Типичные ошибки
1. Фильтрация правой таблицы в WHERE вместо ON
-- Неправильно: превращает LEFT JOIN в INNER JOIN
SELECT u.*, o.order_id
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
WHERE o.status = 'completed';
-- Правильно: условие в ON
SELECT u.*, o.order_id
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
AND o.status = 'completed';В первом варианте WHERE отсечёт все строки, где o.status IS NULL (то есть пользователей без заказов) — LEFT JOIN потеряет смысл.
2. Забыть про дубликаты
Если в правой таблице несколько совпадений, LEFT JOIN вернёт по строке на каждое. Пользователь с 3 заказами появится 3 раза.
Вопросы с собеседований
- «Чем LEFT JOIN отличается от RIGHT JOIN?» — Только порядком таблиц. LEFT JOIN сохраняет левую, RIGHT JOIN — правую. На практике RIGHT JOIN почти не используется.
- «Когда INNER JOIN лучше LEFT JOIN?» — Когда вам не нужны строки без совпадений. INNER JOIN проще читать и иногда быстрее.
- «Как найти пользователей, которые ни разу не заходили?» — LEFT JOIN users с sessions + WHERE sessions.id IS NULL.
FAQ
Можно ли заменить LEFT JOIN на INNER JOIN?
Только если вы уверены, что для каждой строки левой таблицы есть совпадение в правой. Иначе потеряете данные.
RIGHT JOIN — это то же самое, что LEFT JOIN?
По сути да, просто «зеркальный». A LEFT JOIN B = B RIGHT JOIN A. На практике почти все пишут LEFT JOIN и меняют порядок таблиц.
Что быстрее — LEFT JOIN или INNER JOIN?
INNER JOIN обычно чуть быстрее, потому что возвращает меньше строк. Но разница минимальна — выбирайте по смыслу задачи, а не по производительности.