Ответ
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";
Ответ 18+ 🔞
Давайте разберём этот ваш JOIN, а то некоторые думают, что это такой новый вид йоги или марка джинсов. Нет, блядь, это просто способ склеить таблицы в базе данных, чтобы не бегать туда-сюда, как угорелый.
Представьте, у вас есть таблица employees — это ваши работнички, и таблица departments — отделы, где они якобы трудятся. А связывает их какой-нибудь department_id. Вот JOIN — это и есть процесс их сведения, чтобы понять, кто где сидит и, главное, кто вообще нигде не сидит и просто деньги получает.
Основные виды склейки, или "давай поженим эти таблицы":
| Тип JOIN | Что делает (человеческим языком) | На что похоже |
|---|---|---|
INNER JOIN |
Возвращает только тех, у кого есть пара. Сотрудник с отделом, отдел с сотрудником. Одиночек и пустые отделы — нахуй, в результат не попали. | Как встреча выпускников: пришли только те, у кого и имя в списке есть, и сам человек явился. |
LEFT JOIN |
Все сотрудники из левой таблицы — важны! А отдел — если найдётся. Не нашёлся отдел у Васька-стажёра? Ну и хуй с ним, пишем NULL. Главное — список сотрудников полный. |
Как построение на плацу: весь личный состав (слева) есть, а напротив каждого пишем его взвод (справа). Кого не распределили — так и пишем "без взвода". |
RIGHT JOIN |
То же самое, но наоборот. Все отделы важны! А сотрудники в них — если есть. Нет людей в отделе "Потерянные души"? Отдел всё равно в отчёте будет, просто с NULL вместо фамилий. По сути, это LEFT JOIN, но таблицы местами поменяли. |
|
FULL JOIN |
А вот это уже полный пиздец, простите, объединение. Берём ВСЕХ сотрудников и ВСЕ отделы. Кто с кем сошёлся — молодцы. Кто одинок — тоже в списке, но с пустыми полями рядом. Полная картина бардака. | Общая ведомость: и все люди, и все комнаты в офисе. Сопоставляем, кто в какой комнате. Свободные комнаты и бесхозные люди — тоже в списке. |
CROSS JOIN |
А это, блядь, самое весёлое. Декартово произведение, ёпта. Каждого сотрудника женим на каждом отделе. Получаем все возможные пары. Если 100 сотрудников и 10 отделов, будет 1000 строк. Овердохуища комбинаций. Используется редко, иначе сервер взвоет, как сука. | Как если бы вы взяли список всех мужчин и всех женщин в городе и составили абсолютно все возможные пары для свидания. Абсурд, но иногда нужно. |
Как это выглядит в коде, эти ваши запросы:
-- 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, спросите вы? Ну, при всём, ядрёна вошь!
- Чистый JDBC: Ты просто пишешь этот SQL-текст, как есть, в
PreparedStatementи запускаешь. База данных всё сделает, тебе только результат разобрать. -
JPA/Hibernate (этот ваш хайбернейт): Тут уже можно не париться с JOIN вручную, если связи между сущностями (
@ManyToOneи прочая хуйня) настроены. Объекты сами подтянутся. Но если очень хочется поконтролировать, пишем JPQL:// Типичный запрос на ORM-сленге String jpql = "SELECT e FROM Employee e JOIN e.department d WHERE d.name = :deptName";Перевод: "Дай мне всех сотрудников (
e), которые приджойнены к своему отделу (d), но только если отдел называется, например, 'Бухгалтерия'". И не надо самому писатьON e.id = d.id, фреймворк уже всё проеб... то есть, предусмотрел.
Вот и вся магия. Главное — понять, что тебе нужно: только пары, все левые, все правые или вообще все подряд. А то CROSS JOIN на больших таблицах — это верный способ отправить базу в глубокий и долгий запой.