Lecții din modul (2/4)
Manipularea NULL-urilor: IS NULL și COALESCE
În setul de date employees, Andrea Costa este specială: are
department_id = NULL. Te-ai lovit deja de NULL (cu
LEFT JOIN), dar a sosit momentul să o luăm în serios: NULLs în SQL
se comportă diferent față de orice altă valoare, iar ignorarea acestora este una dintre cele
principalele cauze ale erorilor în codul de producție.
NULL nu este zero, nu este șir gol
NULL înseamnă valoare necunoscută/lipsă. Nu este 0, nu '', nu
false. Este "Nu știu". Din aceasta rezultă o proprietate surprinzătoare:
NULL nu este egal cu nimic, nici măcar cu el însuși.
-- All these expressions return NULL (not true!):
SELECT NULL = NULL; -- NULL
SELECT NULL = 0; -- NULL
SELECT NULL <> 'qualcosa'; -- NULLConsecință concretă: WHERE column = NULL nu funcționează niciodată. Trebuie să utilizați
operatorii dedicați IS NULL / IS NOT NULL:
-- Employees without a department:
SELECT first_name, last_name
FROM employees
WHERE department_id IS NULL;
-- Employees WITH a department:
SELECT first_name, last_name
FROM employees
WHERE department_id IS NOT NULL;COALESCE — alternativă NULL
Adesea, doriți să afișați ceva în loc de NULL atunci când datele sunt
lipsește: șirul '(none)', zero, o dată implicită. Funcția care
face exact asta este COALESCE(a, b, c, ...): returnează primul
argument non-NULL în listă.
-- Show the department_id, or 0 if missing:
SELECT first_name, last_name, COALESCE(department_id, 0) AS dept
FROM employees;Combinat cu un LEFT JOIN, devine incredibil de puternic pentru rapoarte:
SELECT e.first_name,
e.last_name,
COALESCE(d.name, '(nessun dipartimento)') AS dipartimento
FROM employees AS e
LEFT JOIN departments AS d ON e.department_id = d.id;Rezultat: toți angajații au revenit, cu numele departamentului sau un explicit etichetă pentru cei care nu au.
NULL și agregate
Funcții agregate ignore NULLs (cu excepția COUNT(*)):
COUNT(department_id)numără doar rândurile cu valoare;AVG(salary)medii ignorândNULLs — nu le tratează ca 0;SUM(...)însumează numai valorile non-NULL.
Acesta este aproape întotdeauna ceea ce îți dorești. Dar este bine de știut: dacă ești
caută "numărul total de angajați" folosește COUNT(*), nu
COUNT(department_id).
Încearcă
Pentru fiecare angajat, afișați prenumele (first_name), numele de familie (last_name) și o coloană „dipartimento_id” care este egală cu departamentul_id sau -1 dacă nu este atribuită. Trei coloane, un rând per angajat.
Afișează indiciu
Utilizați COALESCE(department_id, -1) pentru a înlocui NULL-urile cu -1.
Soluție disponibilă după 3 încercări
Exercițiu de revizuire
Afișează prenumele (prenume), numele (numele) și numele departamentului (departments.name) ale TOȚI angajații, arătând „(nessuno)” atunci când departamentul lipsește. Folosiți LEFT JOIN + COALESCE.
Afișează indiciu
COALESCE(d.name, '(nessuno)') gestionează NULL-ul introdus de LEFT JOIN.
Soluție disponibilă după 3 încercări