Уроки модуля (2/4)
Оставляя все слева: LEFT JOIN
INNER JOIN из предыдущего урока имеет важный побочный эффект: он
удаляет строки, которым нет совпадений. Если у сотрудника нет отдела
(department_id — это NULL), они исчезнут из результата.
Иногда это то, чего ты хочешь. Однако зачастую это не так: в отчете HR
важно видеть все сотрудников, в том числе без отдела,
и знать, кто они. Для этого и нужен LEFT JOIN (полностью LEFT ВНЕШНЕЕ СОЕДИНЕНИЕ).
Как это работает
SELECT columns
FROM table_a
LEFT JOIN table_b ON table_a.x = table_b.y;Прочтите по-английски: "сохраните все строки table_a; для каждой попробуйте
прикрепить строку из table_b; если совпадений нет, заполните столбцы из
table_b с NULL".
Ключевое слово LEFT: оно означает «левый стол», т.е. тот, который написан
после FROM. Все его строки всегда сохраняются.
-- All employees, including those without a department:
SELECT e.first_name,
e.last_name,
d.name AS dipartimento
FROM employees AS e
LEFT JOIN departments AS d ON e.department_id = d.id;В нашем наборе данных этот запрос возвращает 10 строк (по одному сотруднику в каждой). Андреа
Коста, у которого есть department_id = NULL, появляется с dipartimento = NULL
вместо того, чтобы исчезнуть.
Поиск строк «нет совпадений»
Очень полезное последствие: фильтруя с помощью IS NULL в столбце
в правой таблице вы найдете именно те строки без совпадений:
-- Orphan employees: no department assigned
SELECT e.first_name, e.last_name
FROM employees AS e
LEFT JOIN departments AS d ON e.department_id = d.id
WHERE d.id IS NULL;Этот трюк постоянно используется в реальном мире: "найди мне заказы без клиент", "товары без отзывов", "пользователи, которые никогда не авторизовались в".
Попробуйте это
Возвращает имя (first_name) и фамилию (last_name) сотрудников, которым НЕ назначен отдел. Одна или несколько строк, два столбца.
Показать подсказку
Заполните WHERE с помощью d.id IS NULL — вам нужны строки, в которых LEFT JOIN не нашел соответствующий отдел.
Решение доступно после 3 попыток
Обзор упражнения
Перечислите все отделы (departments.name) и рядом с ними количество сотрудников, включая отделы, в которых нет сотрудников (для них покажите 0). Подсказка: начните с отделов и выполните ЛЕВОЕ СОЕДИНЕНИЕ с сотрудниками, затем GROUP BY + COUNT.
Показать подсказку
Используйте COUNT(e.id) (а не COUNT(*)) для подсчета 0, когда совпадений нет: COUNT(*) будет считать 1 из-за строки LEFT JOIN с NULL.
Решение доступно после 3 попыток