WITH RECURSIVE (Interogări Ierarhice și Arboreale în MySQL 8) în MySQL

Citirea datelor MySQL 8.0+

Parcurgerea ierarhiilor arborescente (angajați-manageri, categorii-subcategorii) și a grafurilor relaționale prin clauza recursivă WITH RECURSIVE.

Sintaxă
WITH RECURSIVE ierarhie AS (SELECT id, nume, 1 as nivel FROM angajati WHERE sef_id IS NULL UNION ALL ...) SELECT * FROM ierarhie;

Clauza WITH RECURSIVE permite rularea de interogări auto-referențiale care se apelează repetat până când o condiție de oprire este îndeplinită. Înainte de MySQL 8.0, parcurgerea unui arbore de adâncime necunoscută (cum este o organigramă de angajați sau un meniu infinit de categorii și subcategorii de produse) necesita zeci de interogări separate în PHP/Python sau tabele modificate cu structura Nested Sets.

Parcurgerea ierarhiei complete de categorii dintr-un magazin online
-- Structura tabelului: categorii (id, nume, parinte_id)
WITH RECURSIVE ArboreCategorii AS (
    -- 1. Cazul de bază (Anchor Member): Categoriile rădăcină (fără părinte)
    SELECT 
        id, 
        nume, 
        parinte_id, 
        1 AS nivel,
        CAST(nume AS CHAR(1000)) AS cale_completa
    FROM categorii
    WHERE parinte_id IS NULL

    UNION ALL

    -- 2. Membrul Recursiv (Recursive Member): Unim părintele cu copiii săi
    SELECT 
        c.id, 
        c.nume, 
        c.parinte_id, 
        a.nivel + 1,
        CONCAT(a.cale_completa, ' > ', c.nume)
    FROM categorii c
    INNER JOIN ArboreCategorii a ON c.parinte_id = a.id
)
-- 3. Rezultatul final ordonat ierarhic:
SELECT id, nivel, cale_completa 
FROM ArboreCategorii 
ORDER BY cale_completa;

-- Exemplu de output:
-- 1 | Nivel 1 | Electronice
-- 2 | Nivel 2 | Electronice > Telefoane
-- 3 | Nivel 3 | Electronice > Telefoane > Smartphone-uri

Protecție Împotriva Buclelor Infinite

Pentru a preveni blocarea serverului în cazul în care datele conțin o buclă ciclică (A este părintele lui B, iar B este părintele lui A), MySQL impune o limită automată controlată de variabila de sistem cte_max_recursion_depth (implicit 1.000 de iterații). Poți ajusta limita local:

SET SESSION cte_max_recursion_depth = 5000;