Модульні уроки (2/4)
Зберігаючи все зліва: LEFT JOIN
INNER JOIN з попереднього уроку має важливий побічний ефект: це
відкидає рядки, які не мають відповідності. Якщо у співробітника немає відділу
(department_id є NULL), вони зникають із результату.
Іноді саме цього хочеться. Однак часто це не так: у звіті відділу кадрів
дуже важливо бачити всіх співробітників, включно з тими, хто не має відділу,
і знати, хто вони. Ось для чого призначений LEFT JOIN (повністю, ЛІВОРУЧ ЗОВНІШНЄ З'ЄДНАННЯ).
Як це працює
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 для них). Підказка: почніть із відділів і виконайте ОБ’ЄДНАННЯ ВЛІВО з працівниками, а потім ГРУПУЙТЕ ЗА + ПІДЧИСЛЕННЯМ.
Показати підказку
Використовуйте COUNT(e.id) (а не COUNT(*)), щоб підрахувати 0, коли немає відповідності: COUNT(*) вважатиме 1 через рядок LEFT JOIN із NULL.
Рішення доступне після 3 спроб