Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MYSQL-Ausgabe im Baumformat ODER Hinzufügen von Ebenen (Eltern-Kind)

Obwohl Sie mit einer einzelnen Abfrage nicht auskommen, können Sie mit einer gespeicherten Prozedur auskommen ... Die einzige Voraussetzung ist, dass Sie Ihrer vorhandenen Beispieltabelle zwei weitere Datensätze hinzufügen müssen, um darzustellen, dass "C1" und "C2" SIND die oberste Ebene... Fügen Sie einen Datensatz hinzu, bei dem das Feld "Übergeordnet" leer ist und die untergeordnete Ebene "C1" und eine weitere für "C2" ist. Dadurch wird die oberste übergeordnete Ebene "vorbereitet". für die nachfolgende Hierarchieassoziation, da Sie sonst keine "Basis" der obersten Hierarchie haben. Es erfordert auch eine "Primärschlüssel"-Spalte (die ich in diesem Skript als "IDMyTable" erstellt habe, die nur 1-x sequenziell ist, aber ich würde davon ausgehen, dass Sie stattdessen eine Auto-Increment-Spalte in Ihrer Tabelle verwenden). P>

Ich habe alle Ausgabespalten eingefügt, um zu zeigen, WIE sie erstellt wird, aber die Prämisse dieser Routine besteht darin, eine Tabelle basierend auf den erwarteten Spaltenausgaben zu erstellen, aber zusätzlich, um die hierarchische Darstellung nachgelagert zu halten, während sie erstellt wird. Um SICHERZUSTELLEN, dass sie die richtige Ausrichtung beibehalten, wenn die Schichten tiefer werden, verkette ich die "ID"-Spalte - Sie werden sehen, wie es im endgültigen Ergebnissatz funktioniert.

Dann fülle ich im endgültigen Ergebnissatz Leerzeichen vor, je nachdem, wie tief die Hierarchiedaten sind.

Die Schleife fügt alle Datensätze basierend auf ihrem übergeordneten Element hinzu, das in der vorherigen Ergebnismenge gefunden wurde, aber nur, wenn die ID noch nicht hinzugefügt wurde (Vermeidung von Duplikaten) ...

Um zu sehen, wie die zyklische Reihenfolge ständig angehängt wurde, können Sie die letzte Abfrage OHNE die Reihenfolge von ausführen und sehen, wie jede Iteration qualifiziert und die vorherige Hierarchieebene hinzugefügt wurde ...

-- --------------------------------------------------------------------------------
-- 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