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

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

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

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

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

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

Разница между JOIN и OUTER JOIN

INNER JOIN (обычный JOIN)

Outer JOIN возвращает только строки, где есть совпадения в обеих таблицах. Это самый строгий тип объединения.

-- INNER JOIN (или просто JOIN)
SELECT u.id, u.name, o.order_id
FROM users u
JOIN orders o ON u.id = o.user_id;

-- Результат:
-- id | name   | order_id
-- 1  | Alice  | 101
-- 1  | Alice  | 102
-- 3  | Bob    | 103
-- Пользователь 2 (Charlie) НЕ будет в результате, т.к. у него нет заказов

Визуально:

users               orders
1 Alice      ───→ 101
2 Charlie    
3 Bob        ───→ 103

Результат JOIN: только строки с совпадением (Alice, Bob)

OUTER JOIN

OUTER JOIN возвращает все строки из одной таблицы и совпадающие строки из другой. Есть три варианта:

1. LEFT OUTER JOIN (LEFT JOIN)

Все строки из левой таблицы + совпадающие из правой:

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

-- Результат:
-- id | name    | order_id
-- 1  | Alice   | 101
-- 1  | Alice   | 102
-- 2  | Charlie | NULL     ← нет заказов
-- 3  | Bob     | 103

Визуально:

users               orders
1 Alice      ───→ 101
2 Charlie    ───→ NULL
3 Bob        ───→ 103

Результат LEFT JOIN: ВСЕ пользователи (даже без заказов)

2. RIGHT OUTER JOIN (RIGHT JOIN)

Все строки из правой таблицы + совпадающие из левой:

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

-- Результат:
-- id   | name    | order_id
-- 1    | Alice   | 101
-- 1    | Alice   | 102
-- 3    | Bob     | 103
-- NULL | NULL    | 104      ← заказ от неизвестного пользователя

3. FULL OUTER JOIN

Все строки из обеих таблиц:

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

-- Результат:
-- id   | name    | order_id
-- 1    | Alice   | 101
-- 1    | Alice   | 102
-- 2    | Charlie | NULL     ← пользователь без заказов
-- 3    | Bob     | 103
-- NULL | NULL    | 104      ← заказ от неизвестного пользователя

Сравнение в таблице

Тип JOINЛевая таблицаПравая таблицаОписание
INNERТолько совпаденияТолько совпаденияСтрокам в обеих таблицах
LEFTВсеТолько совпаденияВсе левые + совпадающие правые
RIGHTТолько совпаденияВсеСовпадающие левые + все правые
FULLВсеВсеВсе строки из обеих таблиц

Практический пример на Java с Hibernate

// Энтити User
@Entity
@Table(name = "users")
public class User {
    @Id
    private int id;
    private String name;
    
    @OneToMany(mappedBy = "user")
    private List<Order> orders;
}

// Энтити Order
@Entity
@Table(name = "orders")
public class Order {
    @Id
    private int orderId;
    
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}

// INNER JOIN
String hqlInner = "SELECT u FROM User u INNER JOIN u.orders o";
List<User> usersWithOrders = session.createQuery(hqlInner, User.class).getResultList();
// Только пользователи с заказами

// LEFT JOIN
String hqlLeft = "SELECT DISTINCT u FROM User u LEFT JOIN u.orders o";
List<User> allUsers = session.createQuery(hqlLeft, User.class).getResultList();
// Все пользователи (даже без заказов)

SQL vs Hibernate Query

// SQL INNER JOIN
String sql = "SELECT u.*, o.* FROM users u INNER JOIN orders o ON u.id = o.user_id";

// Hibernate HQL INNER JOIN
String hql = "SELECT u, o FROM User u INNER JOIN u.orders o";

// Hibernate Criteria LEFT JOIN
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> userRoot = query.from(User.class);
userRoot.leftJoin("orders"); // LEFT JOIN
query.select(userRoot);
List<User> users = session.createQuery(query).getResultList();

Визуальное представление всех типов

Users (id=1,2,3)    Orders (user_id=1,1,3,4)

┌─────────────────────────────────────────────┐
│ INNER JOIN → только 1 и 3 (совпадения)    │
├─────────────────────────────────────────────┤
│ LEFT JOIN → 1, 2, 3 (все пользователи)    │
├─────────────────────────────────────────────┤
│ RIGHT JOIN → 1, 3, 4 (все заказы)         │
├─────────────────────────────────────────────┤
│ FULL JOIN → 1, 2, 3, 4 (все + все)        │
└─────────────────────────────────────────────┘

Когда использовать

INNER JOIN:

  • Нужны только совпадающие данные
  • Например: пользователи, которые сделали заказы

LEFT JOIN:

  • Нужны все левые записи с опциональными данными из правой
  • Например: все пользователи со списком их заказов (даже если заказов нет)

RIGHT JOIN:

  • Реже используется, выражается через LEFT JOIN другой таблицы

FULL JOIN:

  • Нужны все записи из обеих таблиц
  • PostgreSQL, Oracle поддерживают, MySQL нет (нужно UNION LEFT + RIGHT)

Вывод

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

В чем разница между JOIN и OUTER JOIN? | PrepBro