Ранее мы рассматривали соединение INNER JOIN
. В его результат попадают только те строки, для которых нашлась пара, удовлетворяющая условию соединения. То есть там могут быть не все строки из первой или второй таблицы. Но бывают задачи, когда мы хотим построить соединение двух таблиц, но так, чтобы в нем были все строки одной из таблиц. Такие задачи можно решать с помощью LEFT JOIN
и RIGHT JOIN
.
Сравниваем INNER JOIN
и LEFT JOIN
Рассмотрим пример с сотрудниками и отделами компании.
Таблица departments
хранит информацию об отделах:
departments
department_id | name |
---|---|
1 | Development Department |
2 | Marketing Department |
3 | Finance Department |
4 | HR Department |
5 | Sales Department |
Таблица employees
хранит информацию о сотрудниках:
employees
employee_id | department_id | name | salary |
---|---|---|---|
1 | 1 | John Smith | 50000.00 |
2 | 1 | Peter Johnson | 60000.00 |
3 | 2 | Mary Brown | 55000.00 |
4 | 2 | Alex Miller | 70000.00 |
5 | 3 | Helen White | 48000.00 |
View on DB Fiddle
В отделах HR (department_id = 4
) и Sales (department_id = 5
) пока еще нет ни одного сотрудника.
Рассмотрим, как работает левое внешнее соединение в сравнении с внутренним соединением.
Начнем с внутреннего соединения:
SELECT
dep.name AS department,
emp.name AS employee
FROM departments AS dep
INNER JOIN employees AS emp ON -- внутреннее соединение
dep.department_id = emp.department_id
Результат внутреннего соединения
department | employee |
---|---|
Development Department | John Smith |
Development Department | Peter Johnson |
Marketing Department | Mary Brown |
Marketing Department | Alex Miller |
Finance Department | Helen White |
View on DB Fiddle
А теперь рассмотрим левое внешнее соединение:
SELECT
dep.name AS department,
emp.name AS employee
FROM departments AS dep
LEFT JOIN employees AS emp ON -- левое внешнее соединение
dep.department_id = emp.department_id
В тексте запроса почти нет отличий — вместо INNER
указано слово LEFT
. Результат выполнения запроса:
department | employee |
---|---|
Development Department | John Smith |
Development Department | Peter Johnson |
Marketing Department | Mary Brown |
Marketing Department | Alex Miller |
Finance Department | Helen White |
Sales Department | NULL |
HR Department | NULL |
View on DB Fiddle
В результате LEFT JOIN
есть все строки из результата INNER JOIN
, но помимо них оно содержит еще две строки — с отделом продаж и HR. В этих отделах нет сотрудников, поэтому в качестве имени сотрудника подставляется NULL
-значение.
Схематично это можно представить следующим образом:
Результат содержит все строки из первой таблицы, даже те, которые не удалось связать.
Сравниваем, как работает группировка
Рассмотрим еще один пример, который подчеркивает разницу между INNER JOIN
и LEFT JOIN
. Допустим, мы хотим посчитать количество сотрудников в каждом из отделов. Такую задачу мы уже решали — надо воспользоваться соединением и группировкой.
Запрос с внутренним соединением
SELECT
dep.name AS department,
COUNT(emp.employee_id) AS employees_count
FROM departments AS dep
INNER JOIN employees AS emp ON
dep.department_id = emp.department_id
GROUP BY dep.name
department | employees_count |
---|---|
Finance Department | 1 |
Marketing Department | 2 |
Development Department | 2 |
View on DB Fiddle
Запрос с левым внешним соединением
SELECT
dep.name AS department,
COUNT(emp.employee_id) AS employees_count
FROM departments AS dep
LEFT JOIN employees AS emp ON
dep.department_id = emp.department_id
GROUP BY dep.name
department | employees_count |
---|---|
Sales Department | 0 |
HR Department | 0 |
Finance Department | 1 |
Marketing Department | 2 |
Development Department | 2 |
View on DB Fiddle
Текст запросов также отличается только типом соединения. А результаты отличаются тем, что в запросе с INNER JOIN
нет отделов с нулевым количеством сотрудников, а в запросе LEFT JOIN
они есть. Разница снова связана с тем, как обрабатываются строки без пары.
RIGHT JOIN
Запрос с RIGHT JOIN
работает так же, как и LEFT JOIN
. Но в результат попадают все строки из второй (правой) таблицы, а не из первой (левой).
Схематично работа RIGHT JOIN
выглядит так:
Результат содержит все строки из второй таблицы, даже те, которые не удалось связать.
Запрос, в котором используется левое внешнее соединение, можно легко переписать на запрос с правым внешним соединением:
Запрос с левым внешним соединением
SELECT
dep.name AS department,
COUNT(emp.employee_id) AS employees_count
FROM departments AS dep
LEFT JOIN employees AS emp ON
dep.department_id = emp.department_id
GROUP BY dep.name
View on DB Fiddle
Запрос с правым внешним соединением
SELECT
dep.name AS department,
COUNT(emp.employee_id) AS employees_count
FROM employees AS emp
RIGHT JOIN departments AS dep ON
dep.department_id = emp.department_id
GROUP BY dep.name
View on DB Fiddle
Эти запросы отличаются только типом соединения и порядком таблиц. То есть можно сказать, что TableA LEFT JOIN TableB
= TableB RIGHT JOIN TableA
.
Выводы
LEFT JOIN
используют, когда нужно построить соединение, в котором обязательно будут все строки из первой таблицы. Если для строки из первой таблицы нет подходящих пар во второй таблице, то вместо данных из второй таблицы будут подставлены NULL
-значения.
RIGHT JOIN
работает похожим образом, но только в результат попадают все строки из второй таблицы, а не из первой.
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.