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 обычно чуть быстрее, потому что возвращает меньше строк. Но разница минимальна — выбирайте по смыслу задачи, а не по производительности.