Lezioni del modulo (2/4)
Gestire i NULL: IS NULL e COALESCE
Nel dataset employees, Andrea Costa è speciale: ha department_id = NULL.
Hai già incontrato NULL di sfuggita (col LEFT JOIN), ma è arrivato il
momento di prenderlo sul serio: i NULL in SQL si comportano in modo
diverso da qualsiasi altro valore, e ignorarli è una delle prime cause di
bug nel codice di produzione.
NULL non è zero, non è stringa vuota
NULL significa valore sconosciuto / assente. Non è 0, non è '', non
è false. È "non lo so". Da questo discende una proprietà sorprendente:
NULL non è uguale a niente, nemmeno a se stesso.
-- Tutte queste espressioni restituiscono NULL (e non true!):
SELECT NULL = NULL; -- NULL
SELECT NULL = 0; -- NULL
SELECT NULL <> 'qualcosa'; -- NULLConseguenza concreta: WHERE colonna = NULL non funziona mai. Devi usare
gli operatori dedicati IS NULL / IS NOT NULL:
-- Dipendenti senza dipartimento:
SELECT first_name, last_name
FROM employees
WHERE department_id IS NULL;
-- Dipendenti CON un dipartimento:
SELECT first_name, last_name
FROM employees
WHERE department_id IS NOT NULL;COALESCE — il fallback per NULL
Spesso vuoi mostrare qualcosa al posto di NULL quando il dato manca: la
stringa '(nessuno)', lo zero, una data di default. La funzione che fa
esattamente questo si chiama COALESCE(a, b, c, ...): restituisce il
primo argomento non-NULL della lista.
-- Mostra il department_id, o 0 se manca:
SELECT first_name, last_name, COALESCE(department_id, 0) AS dept
FROM employees;Con un LEFT JOIN diventa potentissima per i report:
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;Risultato: tutti i dipendenti restituiti, con il nome del dipartimento o l'etichetta esplicita per chi non ne ha uno.
NULL e gli aggregati
Le funzioni di aggregazione ignorano i NULL (eccetto COUNT(*)):
COUNT(department_id)conta solo le righe con un valore;AVG(salary)calcola la media ignorando iNULL, non li tratta come 0;SUM(...)somma solo i non-NULL.
Questo è quasi sempre quello che vuoi. Ma è bene saperlo: se cerchi "il
numero totale di dipendenti" usa COUNT(*), non COUNT(department_id).
Prova tu
Per tutti i dipendenti, mostra nome (first_name), cognome (last_name) e una colonna 'dipartimento_id' che vale il loro department_id oppure -1 se non è assegnato. Tre colonne, una riga per dipendente.
Mostra suggerimento
Usa COALESCE(department_id, -1) per sostituire i NULL con -1.
Soluzione disponibile dopo 3 tentativi
Esercizio di ripasso
Restituisci nome (first_name), cognome (last_name) e nome del dipartimento (departments.name) di TUTTI i dipendenti, mostrando '(nessuno)' quando il dipartimento manca. Usa LEFT JOIN + COALESCE.
Mostra suggerimento
COALESCE(d.name, '(nessuno)') gestisce il NULL introdotto dal LEFT JOIN.
Soluzione disponibile dopo 3 tentativi