Эквисоединения

Соединения, которые мы рассмотрели ранее и которые преобладают в примерах данного учебника, называются соединениями по предикату.

Синтаксис этого вида соединения такой:

Таблица_1 <тип соединения> JOIN Таблица_2 ON <предикат>

где

 тип соединения := [INNER] | [OUTER]{LEFT | RIGHT | FULL}

Эти соединения являются наиболее общими, т.к. в качестве предиката может быть использовано любое логическое выражение. Именно по этой причине все диалекты поддерживают этот вид соединения.

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

При этом соединяемые столбцы зачастую имеют одинаковые имена, поскольку в соединении участвуют таблицы, связанные внешним ключом. Впрочем, последнее не суть важно, т.к. мы можем переименовать столбцы, если это нам потребуется.

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

Естественное соединение

Таблица_1 NATURAL <тип соединения> JOIN Таблица_2

Предикат здесь не нужен, т.к. он подразумевается, а именно попарное равенство всех столбцов с одинаковыми именами в обеих таблицах. Например, если у обеих соединяемых таблиц есть столбцы a и b, то естественное соединение

Таблица_1 NATURAL INNER JOIN Таблица_2

будет эквивалентно такому соединению по предикату:

Таблица_1 INNER JOIN Таблица_2 ON Таблица_1.a = Таблица_2.a AND Таблица_1.b = Таблица_2.b

Кроме того, при естественном соединении одноименные столбцы будут присутствовать в выборке в одном экземпляре. Сравните, например, результаты таких запросов (база данных Аэрофлот)

select * 
from Pass_in_trip
    join Passenger on Pass_in_trip.id_psg = Passenger.id_psg
where trip_no=1123;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]
trip_nodateid_psgplaceid_psgname
11232003-04-05 00:00:0032a3Kevin Costner
11232003-04-08 00:00:0014c1Bruce Willis
11232003-04-08 00:00:0064b6Ray Liotta
select * 
from Pass_in_trip
    NATURAL join Passenger
where trip_no=1123;
mysql
🚫
[[ error ]]
[[ column ]]
[[ value ]]
id_psgtrip_nodateplacename
611232003-04-08 00:00:004bRay Liotta
311232003-04-05 00:00:002aKevin Costner
111232003-04-08 00:00:004cBruce Willis

Как видно из представленных результатов, столбец id_psg, по которому выполняется соединение, не повторяется для естественного соединения.

Из СУБД, доступных на сайте sql-ex.ru, только SQL Server не поддерживает естественное соединение. Если вы хотите поработать с естественным соединением практически, выберите в консоли PostgreSQL или MySQL.

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

Таблица_1 <тип соединения> JOIN Таблица_2 USING(<список столбцов>)

Список столбцов содержит те столбцы, по которым выполняется эквисоединение. Соответственно, в этом списке могут присутствовать только те из столбцов, имена которых совпадают в обеих соединяемых таблицах.

Сравните результаты следующих запросов (предикат в предложении WHERE использован лишь для сокращения размера выборки).

Соединение строк из таблиц Income и Outcome по равенству значений в столбце date (база данных Фирма вторсырья)

select * 
from Income 
    join Outcome USING(date)
where MONTH(date) >= 4;
mysql
🚫
[[ error ]]
[[ column ]]
[[ value ]]
datecodepointinccodepointout
2001-04-13 00:00:00615000714490
2001-04-13 00:00:001015000714490
2001-05-11 00:00:00714500912530
2001-09-13 00:00:0012313501631200
2001-09-13 00:00:0013317501631200
2001-09-13 00:00:0012313501731500
2001-09-13 00:00:0013317501731500

Соединение строк из таблиц Income и Outcome по равенству значений в столбцах date и point

select * 
from Income 
    join Outcome USING(date, point)
where MONTH(date) >= 4;
mysql
🚫
[[ error ]]
[[ column ]]
[[ value ]]
pointdatecodeinccodeout
12001-04-13 00:00:006500074490
12001-04-13 00:00:0010500074490
12001-05-11 00:00:007450092530
32001-09-13 00:00:00121350161200
32001-09-13 00:00:00131750161200
32001-09-13 00:00:00121350171500
32001-09-13 00:00:00131750171500

Соединение строк из таблиц Income и Outcome по равенству значений в столбцах date, point и code

select * 
from Income 
    join Outcome USING(date, point, code);
mysql
🚫
[[ error ]]
[[ column ]]
[[ value ]]
не возвращает строк.

Это соединение по всем столбцам с совпадающими именами эквивалентно естественному соединению

select * 
from Income 
    NATURAL join Outcome;
mysql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Чтобы пояснить вывод в последнем варианте, воспользуемся левым соединением

select * 
from Income 
    left join Outcome USING(date, point, code)
where MONTH(date) >= 4;
mysql
🚫
[[ error ]]
[[ column ]]
[[ value ]]
codepointdateincout
612001-04-13 00:00:005000NULL
712001-05-11 00:00:004500NULL
1012001-04-13 00:00:005000NULL
1232001-09-13 00:00:001350NULL
1332001-09-13 00:00:001750NULL