Join (SQL)

У этого термина существуют и другие значения, см. Join.

JOIN — оператор языка SQL, который является реализацией операции соединения реляционной алгебры. Входит в предложение FROM операторов SELECT, UPDATE и DELETE.

Операция соединения, как и другие бинарные операции, предназначена для обеспечения выборки данных из двух таблиц и включения этих данных в один результирующий набор. Отличительными особенностями операции соединения являются следующие:

* в схему таблицы-результата входят столбцы обеих исходных таблиц (таблиц-операндов), то есть схема результата является «сцеплением» схем операндов;
* каждая строка таблицы-результата является «сцеплением» строки из одной таблицы-операнда со строкой второй таблицы-операнда.

Определение того, какие именно исходные строки войдут в результат и в каких сочетаниях, зависит от типа операции соединения и от явно заданного условия соединения. Условие соединения, то есть условие сопоставления строк исходных таблиц друг с другом, представляет собой логическое выражение (предикат).

При необходимости соединения не двух, а нескольких таблиц, операция соединения применяется несколько раз (последовательно).

SQL-операция JOIN является реализацией операции соединения реляционной алгебры только в некотором приближении, поскольку в реляционной модели данных соединение выполняется над отношениями, которые являются множествами, а в SQL — над таблицами, которые являются мультимножествами. Результаты операций тоже, в общем случае, различны: в реляционной алгебре результат соединения даёт отношение (множество), а в SQL — таблицу (мультимножество).

## Содержание

* 1 Описание оператора
* 2 Виды оператора JOIN
* 2.1 INNER JOIN
* 2.2 OUTER JOIN
* 2.2.1 LEFT OUTER JOIN
* 2.2.2 RIGHT OUTER JOIN
* 2.2.3 FULL OUTER JOIN
* 2.3 CROSS JOIN
* 3 Примечания
* 4 Ссылки

## Описание оператора

[править | править код]

FROM
Table1
{INNER | {LEFT | RIGHT | FULL} OUTER | CROSS } JOIN
Table2
{ON <condition> | USING (field_name [,... n])}

В большинстве СУБД при указании слов `LEFT`, `RIGHT`, `FULL` слово `OUTER` можно опустить. Слово `INNER` также в большинстве СУБД можно опустить.

В общем случае СУБД при выполнении соединения проверяет условие (предикат) condition. Если названия столбцов, по которым происходит соединение таблиц, совпадают, то вместо `ON` можно использовать `USING`. Для `CROSS JOIN` условие не указывается.

Для перекрёстного соединения (декартова произведения) `CROSS JOIN` в некоторых реализациях SQL используется оператор «запятая» (,):

FROM
Table1,
Table2

## Виды оператора JOIN

[править | править код]

Для дальнейших пояснений будут использоваться следующие таблицы:

City (Города)  Id | Name

|

1  | Москва
2  | Санкт-Петербург
3  | Казань
Person (Люди)  Name | CityId

|

Андрей  | 1
Леонид  | 2
Сергей  | 1
Григорий  | 4

### INNER JOIN

[править | править код]

Оператор внутреннего соединения `INNER JOIN` соединяет две таблицы. Порядок таблиц для оператора неважен, поскольку оператор является коммутативным.

Заголовок таблицы-результата является объединением (конкатенацией) заголовков соединяемых таблиц.

Тело результата логически формируется следующим образом. Каждая строка одной таблицы сопоставляется с каждой строкой второй таблицы, после чего для полученной «соединённой» строки проверяется условие соединения (вычисляется предикат соединения). Если условие истинно, в таблицу-результат добавляется соответствующая «соединённая» строка.

Описанный алгоритм действий является строго логическим, то есть он лишь объясняет результат, который должен получиться при выполнении операции, но не предписывает, чтобы конкретная СУБД выполняла соединение именно указанным образом. Существует несколько способов реализации операции соединения, например, соединение вложенными циклами (англ. inner loops join), соединение хешированием (англ. hash join), соединение слиянием (англ. merge join). Единственное требование состоит в том, чтобы любая реализация логически давала такой же результат, как при применении описанного алгоритма.

SELECT *
FROM
Person
INNER JOIN
City
ON Person.CityId = City.Id

Результат:

Person.Name  | Person.CityId  | City.Id  | City.Name

|
|
|

Андрей  | 1  | 1  | Москва
Леонид  | 2  | 2  | Санкт-Петербург
Сергей  | 1  | 1  | Москва

### OUTER JOIN

[править | править код]

Соединение двух таблиц, в результат которого обязательно входят все строки либо одной, либо обеих таблиц.

#### LEFT OUTER JOIN

[править | править код]

Оператор левого внешнего соединения `LEFT OUTER JOIN` соединяет две таблицы. Порядок таблиц для оператора важен, поскольку оператор не является коммутативным.

Заголовок таблицы-результата является объединением (конкатенацией) заголовков соединяемых таблиц.

Тело результата логически формируется следующим образом. Пусть выполняется соединение левой и правой таблиц по предикату (условию) p.

1. В результат включается внутреннее соединение (`INNER JOIN`) левой и правой таблиц по предикату p.
2. Затем в результат добавляются те строки левой таблицы, которые не вошли во внутреннее соединение на шаге 1. Для таких строк столбцы, соответствующие правой таблице, заполняются значениями `NULL`.

SELECT *
FROM
Person -- Левая таблица
LEFT OUTER JOIN
City   -- Правая таблица
ON Person.CityId = City.Id

Результат:

Person.Name  | Person.CityId  | City.Id  | City.Name

|
|
|

Андрей  | 1  | 1  | Москва
Леонид  | 2  | 2  | Санкт-Петербург
Сергей  | 1  | 1  | Москва
Григорий  | 4  | NULL  | NULL

#### RIGHT OUTER JOIN

[править | править код]

Оператор правого внешнего соединения `RIGHT OUTER JOIN` соединяет две таблицы. Порядок таблиц для оператора важен, поскольку оператор не является коммутативным.

Заголовок таблицы-результата является объединением (конкатенацией) заголовков соединяемых таблиц.

Тело результата логически формируется следующим образом. Пусть выполняется соединение левой и правой таблиц по предикату (условию) p.

1. В результат включается внутреннее соединение (`INNER JOIN`) левой и правой таблиц по предикату p.
2. Затем в результат добавляются те строки правой таблицы, которые не вошли во внутреннее соединение на шаге 1. Для таких строк столбцы, соответствующие левой таблице, заполняются значениями `NULL`.

SELECT *
FROM
Person -- Левая таблица
RIGHT OUTER JOIN
City   -- Правая таблица
ON Person.CityId = City.Id

Результат:

Person.Name  | Person.CityId  | City.Id  | City.Name

|
|
|

Андрей  | 1  | 1  | Москва
Сергей  | 1  | 1  | Москва
Леонид  | 2  | 2  | Санкт-Петербург
NULL  | NULL  | 3  | Казань

#### FULL OUTER JOIN

[править | править код]

Оператор полного внешнего соединения `FULL OUTER JOIN` соединяет две таблицы. Порядок таблиц для оператора неважен, поскольку оператор является коммутативным.

Заголовок таблицы-результата является объединением (конкатенацией) заголовков соединяемых таблиц.

Тело результата логически формируется следующим образом. Пусть выполняется соединение первой и второй таблиц по предикату (условию) p. Слова «первой» и «второй» здесь не обозначают порядок в записи выражения (который неважен), а используются лишь для различения таблиц.

1. В результат включается внутреннее соединение (`INNER JOIN`) первой и второй таблиц по предикату p.
2. В результат добавляются те строки первой таблицы, которые не вошли во внутреннее соединение на шаге 1. Для таких строк столбцы, соответствующие второй таблице, заполняются значениями `NULL`.
3. В результат добавляются те строки второй таблицы, которые не вошли во внутреннее соединение на шаге 1. Для таких строк столбцы, соответствующие первой таблице, заполняются значениями `NULL`.

SELECT *
FROM
Person
FULL OUTER JOIN
City
ON Person.CityId = City.Id

Результат:

Person.Name  | Person.CityId  | City.Id  | City.Name

|
|
|

Андрей  | 1  | 1  | Москва
Сергей  | 1  | 1  | Москва
Леонид  | 2  | 2  | Санкт-Петербург
NULL  | NULL  | 3  | Казань
Григорий  | 4  | NULL  | NULL

### CROSS JOIN

[править | править код]

Оператор перекрёстного соединения, или декартова произведения `CROSS JOIN` соединяет две таблицы. Порядок таблиц для оператора неважен, поскольку оператор является коммутативным.

Заголовок таблицы-результата является объединением (конкатенацией) заголовков соединяемых таблиц.

Тело результата логически формируется следующим образом. Каждая строка одной таблицы соединяется с каждой строкой второй таблицы, давая тем самым в результате все возможные сочетания строк двух таблиц.

SELECT *
FROM
Person
CROSS JOIN
City

или

SELECT *
FROM
Person,
City

Результат:

Person.Name  | Person.CityId  | City.Id  | City.Name

|
|
|

Андрей  | 1  | 1  | Москва
Андрей  | 1  | 2  | Санкт-Петербург
Андрей  | 1  | 3  | Казань
Леонид  | 2  | 1  | Москва
Леонид  | 2  | 2  | Санкт-Петербург
Леонид  | 2  | 3  | Казань
Сергей  | 1  | 1  | Москва
Сергей  | 1  | 2  | Санкт-Петербург
Сергей  | 1  | 3  | Казань
Григорий  | 4  | 1  | Москва
Григорий  | 4  | 2  | Санкт-Петербург
Григорий  | 4  | 3  | Казань

Если в предложении WHERE добавить условие соединения (предикат p), то есть ограничения на сочетания кортежей, то результат эквивалентен операции `INNER JOIN` с таким же условием:

SELECT *
FROM
Person,
City
WHERE
Person.CityId = City.Id

Таким образом, выражения `t1, t2 WHERE p` и `t1 INNER JOIN t2 ON p` синтаксически являются альтернативными формами записи одной и той же логической операции внутреннего соединения по предикату p. Синтаксис `CROSS JOIN + WHERE` для операции соединения называют устаревшим, его не рекомендует стандарт SQL ANSI[1][2].

## Примечания

[править | править код]

1. ↑ SR0010: не используйте устаревший синтаксис  (неопр.). Дата обращения: 9 апреля 2012. Архивировано 10 июня 2012 года.
2. ↑ ANSI Joins  (неопр.). Дата обращения: 9 апреля 2012. Архивировано 15 июня 2012 года.

## Ссылки

[править | править код]

* Описание видов Join в Oracle Архивная копия от 3 июня 2017 на Wayback Machine (рус.)
* Jeff Atwood, A Visual Explanation of SQL Joins (англ.)

SQL

Версии|

* SQL-86
* SQL-89
* SQL-92
* SQL:1999
* SQL:2003
* SQL:2006
* SQL:2008
* SQL:2011
* SQL:2016
* SQL:2023

Ключевые слова|

* Alter
* As
* Case
* Create
* Delete
* From
* Insert
* Join
* Merge
* Null
* Prepare
* Select
* Truncate
* Union
* Update
* Where
* With

Связанные статьи|

* Эдгар Кодд
* Реляционная база данных

Части ISO/IEC SQL|

* Framework
* Foundation
* CLI
* PSM
* MED
* OLB
* Schemata
* JRT
* XML

Базы данных

Типы|

* Графовая
* Ключ — значение
* Документоориентированная
* На основе цепочки блоков
* Облачная
* Объектно-ориентированная:
* БД
* СУБД
* Объектно-реляционная СУБД
* Резидентная
* Реляционная:
* модель
* алгебра
* БД
* СУБД
* Столбцовая
* Хронологическая
* NoSQL
* NewSQL

Концепции|

* Модель данных
* Иерархическая модель
* Сетевая модель
* Транзакция
* Журнализация
* упреждающая
* Секционирование
* Сегментирование
* Столбцовое хранение

Объекты|

* Схема
* Отношение
* Столбец
* виртуальный
* Строка
* Таблица
* Представление
* материализованное
* Хранимая процедура
* Триггер
* Курсор
* Индекс
* Табличное пространство

Ключи|

* Первичный
* суррогатный
* Внешний
* Потенциальный
* Суперключ

Компоненты|

* Язык запросов
* Оптимизатор запросов
* Планировщик запросов
* План выполнения запроса
* Кэш запросов
* ODBC
* ADO
* ADO.NET
* JDBC

SQL|

| DML|

* SELECT
* INSERT
* UPDATE
* DELETE
* MERGE

|

DDL|

* CREATE
* ALTER
* DROP
* TRUNCATE

DCL|

* REVOKE
* GRANT

TCL|

* COMMIT
* ROLLBACK
* SAVEPOINT