COALESCE, NULLIF și CASE WHEN în PostgreSQL

JSONB, Array și tipuri avansate PostgreSQL 7.4+ (standard în PostgreSQL 15–17)

Gestionează valorile NULL, previne împărțirea la zero și evaluează logica condițională direct în expresiile SQL.

Sintaxă SQL
COALESCE(val1, val2, 'implicit');nNULLIF(expresie, 0);nCASE WHEN cond1 THEN rez1 ELSE rez_default END;

Ce face COALESCE, NULLIF și CASE WHEN

În SQL, orice operație aritmetică sau concatenare clasică cu NULL produce tot NULL. Pentru a trata curat valorile lipsă și ramificările logice, PostgreSQL pune la dispoziție expresiile condiționale standard: COALESCE, NULLIF și CASE WHEN ... THEN ... ELSE ... END.

COALESCE returnează primul argument non-NULL din listă (evaluând argumentele de la stânga la dreapta doar până găsește unul nenul — short-circuit), iar NULLIF(a, b) returnează NULL dacă a = b, fiind extrem de util pentru transformarea șirurilor goale '' în NULL sau pentru evitarea împărțirii la zero.

Clauze, operatori și argumente

Clauză / Operator Descriere
COALESCE(v1, v2, ...) Returnează prima valoare diferită de NULL dintre argumentele sale; returnează NULL doar dacă toate sunt NULL.
NULLIF(val1, val2) Returnează NULL dacă val1 este egal cu val2; altfel returnează val1.
CASE WHEN cond THEN rez ... END Evaluează condițiile în ordine și returnează rezultatul primei ramuri adevărate (sau ELSE / NULL).
IS DISTINCT FROM / IS NOT DISTINCT FROM Operatori de comparație NULL-safe în PostgreSQL (tratează NULL ca pe o valoare comparabilă obișnuită).

Exemple

Exemplul 1: Curățarea șirurilor goale și afișarea unei valori implicite cu COALESCE și NULLIF

Dacă porecla (nickname) este NULL sau un șir gol '' (transformat în NULL prin NULLIF), folosim numele complet.

SELECT id,
       COALESCE(NULLIF(TRIM(nickname), ''), nume_complet, 'Utilizator Anonim') AS nume_afisat,
       COALESCE(discount_proc, 0) AS discount_aplicat
FROM utilizatori
LIMIT 3;

Rezultat interogare

 id |   nume_afisat   | discount_aplicat 
----+-----------------+------------------
 14 | Andrei Popescu  |                0
 15 | AlexDev         |               10
 16 | Maria Ionescu   |                5
(3 rows)

Exemplul 2: Încadrarea produselor pe segmente de preț și evitarea împărțirii la zero cu CASE și NULLIF

Clasificăm produsele în funcție de preț și calculăm rata de conversie protejând numitorul cu NULLIF(afisari, 0).

SELECT denumire,
       pret,
       CASE
           WHEN pret >= 3000 THEN 'Premium'
           WHEN pret >= 1000 THEN 'Mediu'
           ELSE 'Accesibil'
       END AS segment,
       ROUND(100.0 * vanzari / NULLIF(afisari, 0), 2) AS rata_conversie_proc
FROM statistici_produse;

Rezultat interogare

        denumire        |  pret   |  segment  | rata_conversie_proc 
------------------------+---------+-----------+---------------------
 ProBook Ultra 16 M3    | 8499.99 | Premium   |                3.45
 Monitor IPS 27 inch 4K | 1699.90 | Mediu     |                5.12
 Cablu HDMI 2.1         |   49.90 | Accesibil |                    
(3 rows)

Greșeli frecvente

  • Verificarea egalității cu NULL folosind = NULL sau <> NULL: în SQL rezultatul este întotdeauna UNKNOWN; folosește IS NULL, IS NOT NULL sau operatorul PostgreSQL IS DISTINCT FROM.
  • Amestecarea unor tipuri de date incompatibile în argumentele lui COALESCE sau în ramurile THEN din CASE (ex: COALESCE(pret_numeric, 'Indisponibil') declanșează eroarea COALESCE types numeric and text cannot be matched).

Comenzi și funcții înrudite

  • GROUP BY, HAVING și clauza FILTER: Grupează rândurile pentru agregări și aplică condiții individuale pe fiecare funcție agregată prin FILTER (WHERE …).
  • LAG() și LEAD(): Accesează valoarea unei coloane de pe rândul anterior (LAG) sau următor (LEAD) fără a face self-join.
  • to_char() și EXTRACT(): Formatează date, ore și numere în șiruri personalizate (to_char) sau extrage componente numerice din timestamp-uri (EXTRACT).