К своему стыду, я до сих пор не знаю какие бывают виды join‘ов. Ну что же, попробуем разобраться. Начнем с того, что такое  join?

Join — это операция объединяющая таблицы по какому то столбцу. join‘ы бывают следующих типов:

  • left inner;
  • right inner;
  • left outer;
  • right outer, более экзотических пока касаться не будем.

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

select * from workers;
---------------
name  | type
---------------
john  | developer
steve | manager
bruce | seller
neal  | architect

select * from phones;
------------------
name   | phone
------------------
john   | 100
jeramy | 103
steve  | 102
zach   | 101

Для лучшего понимая, выполним последовательно каждый из join‘ов.

select * from workers left inner join phones on workers.name = phones.name;

Результатом будет список работников, у которых есть номер телефона:

-------------------------------
name  |type        | phone
-------------------------------
john  | developer  | 100
steve | manager    | 102

Результат можно представить в виде диаграммы Венна

Следующий запрос — left outer join

select * from workers left outer join phones on workers.name = phones.name
-------------------------------
name  |type         | phone
-------------------------------
john  | developer   | 100
steve | manager     | 102
bruce | seller      | null
neal  | architect   | null

Результатом этого запроса, как видите, список всех работников, независимо от того, есть ли у них номер телефона или нет.

С right join‘ом будет аналогичная ситуация, с той только разницей, что в выборку будут попадать, строки из второй таблицы.

select * from workers right outer join phones on workers.name = phones.name
-------------------------------
name   |type         | phone
-------------------------------
john   | developer   | 100
steve  | manager     | 102
jeramy | null        | 103
zach   | null        | 101

Результат выполнения right inner join и left inner join одинаковый.

select * from workers right inner join phones on workers.name = phones.name
-------------------------------
name  |type        | phone
-------------------------------
john  | developer  | 100
steve | manager    | 102

Помимо основных типов, есть еще несколько дополнительных. Используются они реже, но все же иногда бывают полезными. Один из таких — full outer join:

select * from workers full outer join phones on workers.name = phones.name

В результирующую выборку попадут строки, попавшие при выполнении левого и правого outer join‘а по отдельности, т.е.

select * from workers full outer join phones on workers.name = phones.name
-------------------------------
name   |type         | phone
-------------------------------
john   | developer   | 100
steve  | manager     | 102
jeramy | null        | 103
zach   | null        | 101
bruce  | seller      | null
neal   | architect   | null

Наложив некоторое ограничение, можно получить строки, не имеющие совпадений по столбцам.

select * from workers  full outer join phones on workers.name = phones.name where phones.phone is null or workers.type is null;
-------------------------------
name   |type         | phone
-------------------------------
jeramy | null        | 103
zach   | null        | 101
bruce  | seller      | null
neal   | architect   | null

Следующий «специфичный» тип — это cross join:

select * from workers cross join phones

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

И напоследок, приведу несколько запросов с использованием join‘ов.

Получение списка работников не имеющих номеров телефонов:

select * from workers left outer join phones where phones.phone is null
-------------------------------
name   |type         | phone
-------------------------------
bruce  | seller      | null
neal   | architect   | null

Получение списка людей, которые не работают, но у которых есть номер телефона:

select * from workers right outer join phones where workers.type is null
-------------------------------
name   |type         | phone
-------------------------------
jeramy | null        | 103
zach   | null        | 101

Это все, что я хотел рассказать. Спасибо, что прочли. Надеюсь эта статья была полезной.

Визуализация запросов