В чем разница между INNER JOIN, LEFT JOIN, RIGHT JOIN и FULL OUTER JOIN?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Типы JOIN в SQL: полное объяснение
JOIN объединяет данные из двух таблиц на основе условия. Различные типы JOIN определяют, какие строки будут включены в результат.
Визуальное представление
Представим две таблицы:
Таблица users:
user_id | name
--------|-------
1 | Alice
2 | Bob
3 | Charlie
Таблица orders:
order_id | user_id | amount
---------|---------|--------
101 | 1 | 100
102 | 2 | 200
103 | 4 | 300
Обратите внимание: user_id=4 существует в orders, но не в users!
1. INNER JOIN
Определение: возвращает только строки, которые найдены в ОБЕИХ таблицах.
SELECT u.user_id, u.name, o.order_id, o.amount
FROM users u
INNER JOIN orders o ON u.user_id = o.user_id;
Результат:
user_id | name | order_id | amount
--------|---------|----------|--------
1 | Alice | 101 | 100
2 | Bob | 102 | 200
Что произошло:
- user_id=3 (Charlie) не в orders → исключен
- order_id=103 (user_id=4) не в users → исключен
- Только совпадающие: 1, 2
Когда использовать: когда нужны только полные пары данных (например, пользователи, которые совершили покупку).
2. LEFT JOIN (LEFT OUTER JOIN)
Определение: возвращает ВСЕ строки из левой таблицы и совпадающие из правой. Несовпадающие строки в правой таблице замещаются NULL.
SELECT u.user_id, u.name, o.order_id, o.amount
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id;
Результат:
user_id | name | order_id | amount
--------|---------|----------|--------
1 | Alice | 101 | 100
2 | Bob | 102 | 200
3 | Charlie | NULL | NULL
Что произошло:
- ALL users остаются (1, 2, 3)
- Charlie не имеет заказа → NULL
- order_id=103 исключён (не из левой таблицы)
Когда использовать: чтобы видеть все пользователи и их заказы (если они есть). Идеально для "Найти пользователей, у которых нет заказов".
SELECT u.user_id, u.name
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
WHERE o.order_id IS NULL; -- Пользователи БЕЗ заказов
3. RIGHT JOIN (RIGHT OUTER JOIN)
Определение: возвращает ВСЕ строки из правой таблицы и совпадающие из левой. Противоположность LEFT JOIN.
SELECT u.user_id, u.name, o.order_id, o.amount
FROM users u
RIGHT JOIN orders o ON u.user_id = o.user_id;
Результат:
user_id | name | order_id | amount
--------|-------|----------|--------
1 | Alice | 101 | 100
2 | Bob | 102 | 200
4 | NULL | 103 | 300
Что произошло:
- ALL orders остаются (101, 102, 103)
- user_id=3 (Charlie) исключён (нет его в orders)
- order_id=103 от неизвестного user_id=4 → NULL в name
Когда использовать: редко. RIGHT JOIN можно заменить LEFT JOIN, переставив таблицы местами.
-- Это эквивалентно:
SELECT o.user_id, u.name, o.order_id, o.amount
FROM orders o
LEFT JOIN users u ON o.user_id = u.user_id;
4. FULL OUTER JOIN (FULL JOIN)
Определение: возвращает ВСЕ строки из обеих таблиц. Несовпадающие замещаются NULL.
SELECT u.user_id, u.name, o.order_id, o.amount
FROM users u
FULL OUTER JOIN orders o ON u.user_id = o.user_id;
Результат:
user_id | name | order_id | amount
--------|---------|----------|--------
1 | Alice | 101 | 100
2 | Bob | 102 | 200
3 | Charlie | NULL | NULL
4 | NULL | 103 | 300
Что произошло:
- ALL пользователи (1, 2, 3)
- ALL заказы (101, 102, 103)
- Charlie нет в orders → NULL
- order_id=103 от unknown user → NULL
Когда использовать: когда нужны оба набора данных полностью. Редко в product analytics.
Сравнительная таблица
| JOIN тип | LEFT таблица | MATCH | RIGHT таблица | Пример результата |
|---|---|---|---|---|
| INNER | ✓ | ✓ | ✓ | Только совпадающие |
| LEFT | ✓ | ✓ | ✓/NULL | Все левые + совпадение |
| RIGHT | ✓/NULL | ✓ | ✓ | Все правые + совпадение |
| FULL | ✓ | ✓ | ✓ | Всё, но отдельные |
Практические примеры в product analytics
1. Найти пользователей БЕЗ покупок
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; -- Не купили
2. Найти заказы от неизвестных пользователей
SELECT o.order_id, o.user_id, u.name
FROM orders o
LEFT JOIN users u ON o.user_id = u.user_id
WHERE u.user_id IS NULL; -- Заказ от несуществующего user_id
Это может указывать на ошибку в данных!
3. Сравнить активность в двух периодах
SELECT
COALESCE(p1.user_id, p2.user_id) as user_id,
p1.events as events_period1,
p2.events as events_period2
FROM period1_users p1
FULL OUTER JOIN period2_users p2 ON p1.user_id = p2.user_id;
4. Анализ funnel: кто просмотрел, но не купил
SELECT
v.user_id,
COUNT(v.view_id) as views,
COUNT(o.order_id) as orders
FROM page_views v
LEFT JOIN orders o ON v.user_id = o.user_id
GROUP BY v.user_id
HAVING COUNT(o.order_id) = 0; -- Просмотрел, но не купил
Производительность
INNER JOIN — самый быстрый (меньше данных) LEFT/RIGHT JOIN — медленнее (больше данных) FULL OUTER JOIN — самый медленный
Ошибки при использовании
❌ Ошибка 1: забыть ON условие
-- Неправильно: это создаст cartesian product!
SELECT * FROM users u, orders o;
-- Правильно:
SELECT * FROM users u JOIN orders o ON u.user_id = o.user_id;
❌ Ошибка 2: использовать WHERE вместо ON для фильтрации
-- Проблема: LEFT JOIN + WHERE отсеивает NULL
SELECT *
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
WHERE o.amount > 100; -- Это превращает LEFT в INNER!
-- Правильно:
SELECT *
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id AND o.amount > 100;
❌ Ошибка 3: неправильный порядок для RIGHT JOIN
-- Сложно понять:
SELECT * FROM users u RIGHT JOIN orders o ...
-- Лучше:
SELECT * FROM orders o LEFT JOIN users u ...
Роль Product Analyst
Product Analyst часто использует:
- LEFT JOIN — 80% случаев (найти всех пользователей + данные о них)
- INNER JOIN — 15% (только полные пары)
- FULL OUTER JOIN — 5% (редко)
Освоение JOIN — критичный навык для любого аналитика, работающего с SQL.