⛓️🗄️ Соединения в SQL. Часть 1. Типы соединений и простые примеры
Соединения — это способ получения данных из нескольких таблиц с помощью SQL. В первой части статьи мы расскажем о типах соединений и рассмотрим несколько базовых примеров.
Типы соединений SQL
Тип соединения | Описание |
INNER JOIN (ВНУТРЕННЕЕ СОЕДИНЕНИЕ) | Возвращает те строки, для которых в обеих таблицах выполняется условие соединения. |
LEFT JOIN (ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ или просто ЛЕВОЕ СОЕДИНЕНИЕ) | Возвращает строки, содержащие данные из левой таблицы (указанной слева от ключевого слова JOIN ), даже если в правой таблице нет совпадающих строк.
В строках, где нет совпадения справа, все столбцы справа будут заполнены значением NULL . |
RIGHT JOIN(ПРАВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ или просто ПРАВОЕ СОЕДИНЕНИЕ) | Возвращает строки, содержащие данные из правой таблицы (указанной справа от ключевого слова JOIN), даже если в левой таблице нет совпадающих строк.
В строках, где нет совпадения слева, все столбцы слева будут заполнены значением NULL . |
FULL JOIN (ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ или просто ПОЛНОЕ СОЕДИНЕНИЕ) | Возвращает строки, содержащие данные из обеих таблиц.
В строках, где нет совпадения слева или справа, все столбцы без совпадения будут заполнены значением NULL . |
CROSS JOIN (ПЕРЕКРЕСТНОЕ СОЕДИНЕНИЕ) | Возвращает строки, содержащие все возможные комбинации левой и правой частей соединения. Такое соединение называют «декартовым произведением» (прим. перев.) |
Есть еще несколько терминов, которые используются для операций соединения:
Термин | Описание |
Self-join (самосоединение) | Соединение данных в таблице с данными в этой же таблице (с самой собой) |
Natural join (естественное соединение) | Неявное соединение двух таблиц за счет совпадения имен столбцов в этих таблицах |
Equi-join (равнозначное соединение) | Соединение двух таблиц, в условии которого используется только операция равенства (= ) |
Синтаксис соединений
Внутреннее соединение (inner join) может быть описано с помощью предложений FROM
или WHERE
в операторе SELECT
или других операторах DML (data manipulation language, языка манипулирования данными).
Чтобы создать соединение с помощью предложения FROM
, нужно поступить следующим образом:
Здесь конструкция
указывает тип соединения, которое мы хотим получить, а <JoinType>
JoinCondition
– это логическое выражение (предикат), которое должно быть вычислено для каждой пары соединяемых строк.
Чтобы создать соединение с помощью предложения WHERE
, напишите так:
В этом случае JoinCondition
– это тоже логическое выражение, которое должно быть вычислено для каждой пары соединяемых строк.
Любая часть предложения, заключенная в квадратные скобки
, является необязательной.[ ]
Таблицы данных для наших примеров
Для демонстрации примеров соединений мы будем использовать две таблицы с данными:
- Таблицу PetTypes
- Таблицу Pets
Внутреннее соединение (INNER JOIN)
Внутреннее соединение в SQL возвращает строки, для которых в обеих таблицах выполняется условие соединения:
Результат:
Чтобы указать внутренние соединения в предложении FROM
, нужно использовать ключевые слова INNER JOIN
. Далее после слова ON
мы должны описать предикат, соединяющий части строк из наших двух таблиц.
При любом типе соединения нам желательно указывать имена столбцов вместе с именами таблиц, в которых они содержатся. Такой способ записи позволяет избежать неоднозначностей из-за того, что в разных таблицах могут быть столбцы с одинаковыми именами (как в нашем примере). СУБД просто не поймет, из какой таблицы нужно взять столбец. Использование имени таблицы как префикса решит эту проблему. В нашем примере в обеих таблицах есть столбец PetTypeId
. В таблице Pets
этот столбец используется в качестве внешнего ключа, а в таблице PetTypes
– в качестве первичного.
В результате мы получили не все виды питомцев, так как в таблице Pets
у нас нет кроликов (rabbit), хотя в таблице PetTypes
они есть. Причина в том, что внутреннее соединение возвращает только соединенные строки, для которых условие соединения выполняется в обеих таблицах.
Обратите внимание, что для внутреннего соединения слово INNER
часто не является обязательным. Многие (но не все) СУБД позволяют сокращать тип соединения до слова JOIN
, что предполагает именно внутреннее соединение таблиц.
Поэтому наш пример мог бы быть записан короче:
Для простоты всё предложение FROM
можно записать в одну строку:
Псевдонимы
Часто для сокращения записи соединений используют псевдонимы таблиц. Такую запись становится проще читать.
Например, можно переписать предыдущий запрос так:
Результат:
Равнозначное соединение
Соединение, показанное выше, называется еще равнозначным соединением. Такое соединение содержит внутри предиката только операции «равно» (=
).
Есть и другой способ описать такое соединение:
Результат:
Это пример описания внутреннего соединения с помощью предложения WHERE
. Мы указали список таблиц, просто перечислив их через запятую, а условие соединения перенесли в предложение WHERE
. Если бы мы не указали такое условие, то мы получили бы перекрестное соединение (cross join).
Многие начинающие считают такой способ записи внутреннего соединения более простым, чем с использованием слов INNER JOIN
. Вы вправе выбрать любой из двух вариантов на свой вкус, но учтите, что способ записи с использованием INNER JOIN
считается более профессиональным.
Правое соединение (RIGHT JOIN)
Правое соединение, которое еще называют правым внешним соединением, возвращает строки, в которых всегда есть правая часть (полученная из таблицы, стоящей справа от слова JOIN
). Строка будет получена, даже если в левой части не нашлось значений, которые описаны предикатом.
Результат:
В этом результате мы видим строки с видом «кролик» (rabbit), которых не было в выборке после внутреннего соединения. Напротив слова «Rabbit» в колонке PetName
(имя питомца) стоит значение NULL
.
Левое соединение (LEFT JOIN)
Как и правое соединение, левое соединение называют левым внешним соединением. Оно возвращает строки, в которых всегда есть левая часть (полученная из таблицы, стоящей слева от слова JOIN
). Строка будет получена, даже если в правой части не нашлось значений, которые описаны предикатом. Левое соединение по своему смыслу противоположно правому соединению.
Если немного изменить предыдущий пример с использованием левого соединения, то он будет выглядеть так:
Результат:
В этом конкретном случае наш результат совпадает с результатом внутреннего соединения. Однако если мы поменяем местами таблицы в предложении FROM
, тогда мы получим такую же выборку, как и при правом соединении.
Результат:
Как видите, разница в результатах между левым и правым соединениями зависит исключительно от того, как вы располагаете таблицы в предложении
.FROM