← Назад к вопросам

В чем разница между INNER JOIN и LEFT JOIN?

1.6 Junior🔥 271 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

В чем разница между INNER JOIN и LEFT JOIN?

INNER JOIN и LEFT JOIN — это два различных типа операций объединения таблиц в SQL. Основное различие заключается в том, какие строки включаются в результирующий набор данных.

INNER JOIN

INNER JOIN возвращает только те строки, которые имеют совпадения в обеих таблицах. Если строка из левой таблицы не имеет соответствия в правой таблице, она не будет включена в результат.

Синтаксис:

SELECT u.id, u.name, o.order_id
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

Визуально (диаграмма Венна):

Таблица users:        Таблица orders:
id | name             user_id | order_id
1  | Alice            1       | 101
2  | Bob              1       | 102
3  | Charlie          3       | 103
4  | David            NULL    | (нет)

Результат INNER JOIN:
id | name    | order_id
1  | Alice   | 101
1  | Alice   | 102
3  | Charlie | 103

(Bob и David исключены, так как нет совпадений)

LEFT JOIN

LEFT JOIN возвращает все строки из левой таблицы и соответствующие строки из правой таблицы. Если для строки из левой таблицы нет совпадения в правой таблице, значения из правой таблицы будут NULL.

Синтаксис:

SELECT u.id, u.name, o.order_id
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

Результат LEFT JOIN с теми же данными:

id | name    | order_id
1  | Alice   | 101
1  | Alice   | 102
2  | Bob     | NULL
3  | Charlie | 103
4  | David   | NULL

(Все пользователи включены, даже те, кто не сделал заказы)

Таблица сравнения

АспектINNER JOINLEFT JOIN
Включает все строки левой таблицыНетДа
Включает все строки правой таблицыНетНет
Требует совпадение в обеих таблицахДаНет
Может быть NULL в результатеНетДа
Количество строкМожет быть меньшеРавно или больше

Практические примеры

Пример 1: Найти только пользователей с заказами

SELECT u.id, u.name, COUNT(o.id) as order_count
FROM users u
INNER JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name;

Результат: только Alice (2 заказа) и Charlie (1 заказ). Bob и David исключены.

Пример 2: Найти всех пользователей и их заказы (если есть)

SELECT u.id, u.name, o.order_id, o.total_amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

Результат: все пользователи, включая тех, кто не сделал заказы (с NULL в order_id).

Пример 3: Найти пользователей БЕЗ заказов

SELECT u.id, u.name
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE o.user_id IS NULL;

Результат: Bob и David (у которых нет заказов).

Реализация в Java с использованием Hibernate/JPA

// INNER JOIN
@Query("SELECT new map(u.id as userId, u.name as userName, o.orderId as orderId) " +
       "FROM User u INNER JOIN Order o ON u.id = o.user.id")
List<Map<String, Object>> getUsersWithOrders();

// LEFT JOIN
@Query("SELECT new map(u.id as userId, u.name as userName, o.orderId as orderId) " +
       "FROM User u LEFT JOIN Order o ON u.id = o.user.id")
List<Map<String, Object>> getAllUsersWithOrders();

// Нативный SQL INNER JOIN
@Query(value = "SELECT u.id, u.name, o.order_id " +
               "FROM users u INNER JOIN orders o ON u.id = o.user_id",
       nativeQuery = true)
List<Object[]> getUsersWithOrdersNative();

// Нативный SQL LEFT JOIN
@Query(value = "SELECT u.id, u.name, o.order_id " +
               "FROM users u LEFT JOIN orders o ON u.id = o.user_id",
       nativeQuery = true)
List<Object[]> getAllUsersWithOrdersNative();

Производительность

INNER JOIN:

  • Обычно быстрее, чем LEFT JOIN
  • Возвращает меньше строк
  • Легче оптимизировать для планировщика запросов

LEFT JOIN:

  • Может быть медленнее при больших таблицах
  • Возвращает больше данных (с NULL)
  • Требует больше памяти

Примерный запрос:

INNER JOIN: 100 тысяч строк
LEFT JOIN:  1 млн строк (если у большинства нет совпадений)

Правильный выбор

Используйте INNER JOIN когда:

  • Вам нужны только связанные данные
  • Отсутствие совпадения означает, что данные не требуются
  • Хотите исключить orphaned records (пример: заказы без пользователей)

Используйте LEFT JOIN когда:

  • Нужны ВСЕ данные из левой таблицы
  • Нужно найти отсутствующие связи (IS NULL)
  • Нужна полнота данных, даже если нет совпадения

Другие типы JOIN

-- RIGHT JOIN (как LEFT, но для правой таблицы)
SELECT * FROM users u RIGHT JOIN orders o ON u.id = o.user_id;

-- FULL OUTER JOIN (все строки из обеих таблиц)
SELECT * FROM users u FULL OUTER JOIN orders o ON u.id = o.user_id;

-- CROSS JOIN (декартово произведение)
SELECT * FROM users u CROSS JOIN orders o;

Итоговое резюме

Основное отличие:

  • INNER JOIN — только совпадающие строки
  • LEFT JOIN — все строки из левой таблицы + совпадения из правой

Выбор между ними критичен для корректности результатов и производительности запроса.