Mysql
 sql >> Database >  >> RDS >> Mysql

Output MYSQL in formato albero OPPURE Aggiunta di livello (genitore-figlio)

Anche se non puoi farlo con una singola query, puoi farlo con una stored procedure ... L'unico prerequisito, è necessario aggiungere altri 2 record alla tabella di esempio esistente per rappresentare che "C1" e "C2" SONO il livello superiore... Aggiungi un record in cui il campo "Genitore" è vuoto e il livello figlio è "C1" e un altro per "C2". Questo "preparerà" il livello genitore più in alto. per l'associazione gerarchica successiva, altrimenti non si ha alcuna "base" iniziale della gerarchia di livello superiore. Richiede anche una colonna "chiave primaria" (che ho creato in questo script come "IDMyTable" che è solo 1x sequenziale, ma presuppone che tu abbia una colonna di incremento automatico sulla tabella da usare).

Ho incluso tutte le colonne di output per mostrare COME è stata creata, ma la premessa di questa routine è creare una tabella basata sugli output delle colonne previsti, ma in più per mantenere la rappresentazione gerarchica a valle mentre viene costruita. PER ASSICURARSI che mantengano l'orientamento corretto man mano che i livelli diventano più profondi, sto concatenando la colonna "ID":vedrai come funziona nel set di risultati finale.

Quindi, nel set di risultati finale, prepassaggio gli spazi in base alla profondità dei dati della gerarchia.

Il ciclo aggiungerà tutti i record in base al fatto che il genitore è stato trovato nel set di risultati precedente, ma solo se l'ID non è già stato aggiunto (evita i duplicati)...

Per vedere come è stato aggiunto costantemente l'ordine ciclico, puoi eseguire l'ultima query SENZA l'ordine entro e vedere come ogni iterazione è stata qualificata e aggiunto il livello gerarchico precedente è stato applicato...

-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$

CREATE DEFINER=`root`@`localhost` PROCEDURE `GetHierarchy2`()
BEGIN
    -- prepare a hierarchy level variable 
    set @hierlvl := 00000;

    -- prepare a variable for total rows so we know when no more rows found
    set @lastRowCount := 0;

    -- pre-drop temp table
    drop table if exists MyHierarchy;

    -- now, create it as the first level you want... 
    -- ie: a specific top level of all "no parent" entries
    -- or parameterize the function and ask for a specific "ID".
    -- add extra column as flag for next set of ID's to load into this.
    create table MyHierarchy as
    select 
            t1.IDMyTable,
            t1.Child AS Parent,
            @hierlvl as IDHierLevel,
            cast( t1.IDMyTable as char(100)) FullHierarchy
        from
            MyTable t1
        where
                t1.Parent is null
            OR t1.Parent = '';


    -- how many rows are we starting with at this tier level
    set @lastRowCount := ROW_COUNT();

    -- we need to have a "primary key", otherwise our UPDATE
    -- statement will nag about an unsafe update command
    alter table MyHierarchy add primary key (IDMyTable);


    -- NOW, keep cycling through until we get no more records
    while @lastRowCount > 0 do

        -- NOW, load in all entries found from full-set NOT already processed
        insert into MyHierarchy
            select 
                    t1.IDMyTable,
                    t1.Child as Parent,
                    h1.IDHierLevel +1 as IDHierLevel,
                    concat_ws( ',', h1.FullHierarchy, t1.IDMyTable ) as FullHierarchy
                from
                    MyTable t1
                        join MyHierarchy h1
                            on t1.Parent = h1.Parent
                    left join
                        MyHierarchy h2
                            on t1.IDMyTable = h2.IDMyTable
                where
                    h2.IDMyTable is null;


        set @lastRowCount := row_count();

        -- now, update the hierarchy level
        set @hierLevel := @hierLevel +1;

    end while;


    -- return the final set now
    select 
            *, concat( lpad( ' ', 1 + (IDHierLevel * 3 ), ' ' ), Parent ) as ShowHierarchy
        from MyHierarchy
        order by FullHierarchy;

END