Какие типы JOIN существуют в SQL и чем они отличаются?

«Какие типы JOIN существуют в SQL и чем они отличаются?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

JOIN — это операция SQL для объединения строк из двух или более таблиц на основе логической связи между ними.

Основные типы JOIN (на примере таблиц employees и departments):

Тип JOIN Описание Визуализация (Венна)
INNER JOIN Возвращает только строки, где есть совпадение в обеих таблицах. Пересечение множеств.
LEFT (OUTER) JOIN Возвращает все строки из левой таблицы и совпадающие строки из правой. Если совпадения нет, поля правой таблицы будут NULL. Все левое множество + пересечение.
RIGHT (OUTER) JOIN Возвращает все строки из правой таблицы и совпадающие строки из левой. Аналог LEFT JOIN с поменянными таблицами. Все правое множество + пересечение.
FULL (OUTER) JOIN Возвращает строки при наличии совпадения в любой из таблиц. Объединение LEFT и RIGHT JOIN. Полное объединение множеств.
CROSS JOIN Возвращает декартово произведение строк — каждая строка первой таблицы соединяется с каждой строкой второй. Все со всеми.

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

-- INNER JOIN: Сотрудники с известным отделом
SELECT e.name, d.department_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;

-- LEFT JOIN: Все сотрудники, даже без отдела
SELECT e.name, d.department_name
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;

-- FULL JOIN: Все сотрудники и все отделы
SELECT e.name, d.department_name
FROM employees e
FULL OUTER JOIN departments d ON e.department_id = d.id;

-- CROSS JOIN: Все возможные комбинации (редко используется напрямую)
SELECT e.name, d.department_name
FROM employees e
CROSS JOIN departments d;

В контексте Java и JPA:

  • JDBC: JOIN выполняется на уровне SQL-запроса, передаваемого через Statement или PreparedStatement.
  • JPA/Hibernate: JOIN часто реализуется неявно через навигацию по связям между сущностями (аннотации @ManyToOne, @OneToMany). Явный JOIN можно написать в JPQL:
    // JPQL пример
    String jpql = "SELECT e FROM Employee e JOIN e.department d WHERE d.name = :deptName";