Реляционная модель хранит данные в разных таблицах, и почти любой практический запрос требует собрать их обратно в одну картину. Для этого служат соединения — операторы JOIN. Аналитику важно понимать не синтаксис ради синтаксиса, а логику: какие строки попадут в результат, где появятся NULL и почему неверно выбранный тип соединения незаметно искажает цифры в отчёте. Эта статья — учебный разбор основных видов соединений и их отличий от похожего оператора UNION.
1. Зачем нужны соединения
В реляционных базах данные распределены по нескольким таблицам, чтобы избежать дублирования. Чтобы получить целостную картину, таблицы соединяют по ключу — общему столбцу, значения которого связывают строки. Именно для этого и существуют операторы JOIN.
Связи между таблицами обычно проектируются заранее и фиксируются на схемах — см. 03.03.01 ER-диаграммы (сущность-связь). Общий контекст работы аналитика с базами данных разобран в 07.01 Базы данных и SQL на уровне аналитика.
2. Основные виды соединений
Ниже — пять базовых типов соединений. Для каждого указано, какие строки попадают в результат.
| Тип | Что возвращает | Когда применять |
|---|---|---|
INNER JOIN | Только строки с совпадением в обеих таблицах | Нужны лишь записи, у которых есть соответствие по ключу |
LEFT JOIN | Все строки левой таблицы + совпадения из правой | Важно сохранить все данные левой таблицы |
RIGHT JOIN | Все строки правой таблицы + совпадения из левой | Зеркальный случай: важна правая таблица |
FULL JOIN | Строки при совпадении хотя бы в одной таблице | Нужны все данные из обеих таблиц |
CROSS JOIN | Декартово произведение строк | Нужны все возможные комбинации |
INNER JOIN
Возвращает только те строки, которые имеют совпадения в обеих таблицах. Самый распространённый тип соединения.
SELECT A.name, B.salary
FROM employees A
INNER JOIN salaries B ON A.employee_id = B.employee_id;LEFT JOIN (LEFT OUTER JOIN)
Выбирает все записи из первой (левой) таблицы и добавляет совпадающие по ключу записи из второй (правой). Если в правой таблице нет соответствующей записи, для её полей в результате будут значения NULL.
SELECT A.name, B.salary
FROM employees A
LEFT JOIN salaries B ON A.employee_id = B.employee_id;RIGHT JOIN (RIGHT OUTER JOIN)
Зеркальный вариант LEFT JOIN: возвращает все строки из правой таблицы и совпадающие строки из левой. Если совпадения нет, для полей левой таблицы возвращается NULL.
SELECT A.name, B.salary
FROM employees A
RIGHT JOIN salaries B ON A.employee_id = B.employee_id;FULL JOIN (FULL OUTER JOIN)
Возвращает строки, когда есть совпадения хотя бы в одной из таблиц. По сути это объединение LEFT JOIN и RIGHT JOIN.
SELECT A.name, B.salary
FROM employees A
FULL JOIN salaries B ON A.employee_id = B.employee_id;CROSS JOIN
Возвращает декартово произведение двух таблиц: каждая строка из первой таблицы соединяется с каждой строкой из второй.
SELECT A.name, B.salary
FROM employees A
CROSS JOIN salaries B;3. INNER JOIN и просто JOIN — в чём разница
Частый вопрос: чем отличаются INNER JOIN и просто JOIN? По сути это идентичные операторы. JOIN без уточнений по умолчанию воспринимается как INNER JOIN: оба объединяют записи по заданному условию и возвращают только те строки, которые соответствуют условию объединения в обеих таблицах.
Следующие два запроса абсолютно одинаковы:
-- Вариант с INNER JOIN
SELECT table1.column1, table2.column2
FROM table1
INNER JOIN table2 ON table1.id = table2.id;
-- Вариант с JOIN
SELECT table1.column1, table2.column2
FROM table1
JOIN table2 ON table1.id = table2.id;Разницы между ними нет — второй вариант является сокращённой формой первого. Тем не менее явное указание INNER JOIN подчёркивает, что это внутреннее соединение, и может повысить читаемость запроса.
4. OUTER JOIN: что это такое
OUTER JOIN — общее название для соединений, которые берут записи даже тогда, когда совпадений нет. Это противоположность INNER JOIN, который оставляет только совпадения. Когда говорят «OUTER JOIN», обычно подразумевают одну из трёх разновидностей:
LEFT OUTER JOIN(или простоLEFT JOIN)RIGHT OUTER JOIN(или простоRIGHT JOIN)FULL OUTER JOIN(или простоFULL JOIN)
Таким образом, LEFT OUTER JOIN и LEFT JOIN — это одно и то же, просто краткая и полная формы записи. В реальной практике слово OUTER обычно опускают, но его использование тоже корректно.
5. Наглядный пример
Чтобы разобраться в различиях JOIN, удобно представить две таблицы: «пацаны» и «тачки», которыми они владеют.
Таблица №1 (пацаны):
id | имя
--------
1 | Димон
2 | Серёга
3 | ВованТаблица №2 (тачки):
id | машина | владелец_id
-------------------------------
1 | BMW | 1
2 | Audi | 2
3 | Mercedes | 4Результаты разных типов соединений:
- INNER JOIN — только те пацаны, у которых реально есть тачка:
имя | машина
---------------
Димон | BMW
Серёга | Audi- LEFT JOIN — все пацаны, даже если у кого-то нет машины (тогда
NULL):
имя | машина
---------------
Димон | BMW
Серёга | Audi
Вован | NULL- RIGHT JOIN — все машины, даже если владельца нет в таблице пацанов (тогда
NULL):
имя | машина
---------------
Димон | BMW
Серёга | Audi
NULL | Mercedes- FULL JOIN — всё из обеих таблиц, с
NULLтам, где нет совпадений:
имя | машина
---------------
Димон | BMW
Серёга | Audi
Вован | NULL
NULL | Mercedes6. CROSS JOIN подробнее
CROSS JOIN соединяет каждую строку первой таблицы с каждой строкой второй — это «декартово произведение» (Cartesian product). Если в первой таблице 3 записи, а во второй 4, результатом будет 3 × 4 = 12 строк.
SELECT A.X, B.Y
FROM A
CROSS JOIN B;Особенности CROSS JOIN:
- не требует условия соединения (
ONилиUSING); - часто используется для генерации всех возможных комбинаций строк из двух таблиц;
- может привести к огромному количеству строк, если таблицы большие, поэтому применять его следует осторожно.
На практике CROSS JOIN используется редко — в специальных случаях, когда нужны именно все комбинации строк.
7. UNION и его отличие от JOIN
Помимо JOIN, в SQL существует оператор UNION, который тоже объединяет данные, но иначе. UNION объединяет результаты двух или более запросов в один общий результат. Основное условие — все запросы должны возвращать одинаковое количество столбцов с совместимыми типами данных.
Существует два варианта:
UNION— объединяет результаты, удаляя повторяющиеся строки:
SELECT id, name FROM Employees
UNION
SELECT id, name FROM Contractors;UNION ALL— объединяет результаты, сохраняя все строки, включая повторяющиеся:
SELECT id, name FROM Employees
UNION ALL
SELECT id, name FROM Contractors;Ключевые отличия UNION от JOIN:
UNIONобъединяет данные вертикально (один результат помещается под другим), аJOIN— горизонтально (таблицы объединяются по совпадающим столбцам).UNIONтребует совпадения количества столбцов и их типов данных у объединяемых запросов.JOINпозволяет соединять таблицы по произвольным условиям и формировать строки с данными из нескольких таблиц одновременно.
UNION удобно использовать, когда нужно объединить данные из разных источников с одинаковой структурой, тогда как JOIN применяется для объединения взаимосвязанных таблиц.