Реляционная модель хранит данные в разных таблицах, и почти любой практический запрос требует собрать их обратно в одну картину. Для этого служат соединения — операторы 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   | Mercedes

6. 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 применяется для объединения взаимосвязанных таблиц.