Mysql
 sql >> Base de données >  >> RDS >> Mysql

Sortie MYSQL sous forme d'arborescence OU Niveau d'ajout (Parent-Enfant)

Bien que vous ne puissiez pas faire avec une seule requête, vous pouvez le faire avec une procédure stockée... La seule condition préalable, vous devez ajouter 2 enregistrements supplémentaires à votre exemple de table existant pour représenter que "C1" et "C2" SONT le niveau supérieur... Ajoutez un enregistrement où le champ "Parent" est vide, et le niveau enfant est "C1" et un autre pour "C2". Cela "préparera" le niveau parent le plus élevé. pour une association de hiérarchie ultérieure, sinon vous n'avez pas de "base" de départ de la hiérarchie de niveau supérieur. Il nécessite également une colonne "clé primaire" (que j'ai créée dans ce script en tant que "IDMyTable" qui est juste 1-x séquentielle, mais supposerait que vous avez une colonne d'auto-incrémentation sur votre table à utiliser à la place).

J'ai inclus toutes les colonnes de sortie pour montrer COMMENT elle est construite, mais le principe de cette routine est de créer une table basée sur les sorties de colonne attendues, mais supplémentaire pour maintenir la représentation hiérarchique en aval pendant sa construction. Pour S'ASSURER qu'ils conservent la bonne orientation à mesure que les calques s'approfondissent, je concatine la colonne "ID" -- vous verrez comment cela fonctionne dans le jeu de résultats final.

Ensuite, dans le jeu de résultats final, je pré-remplis les espaces en fonction de la profondeur des données de la hiérarchie.

La boucle ajoutera tous les enregistrements en fonction de leur parent trouvé dans le jeu de résultats précédent, mais uniquement si l'ID n'a pas déjà été ajouté (éviter les doublons)...

Pour voir comment l'ordre cyclique a été constamment ajouté, vous pouvez exécuter la dernière requête SANS l'ordre par et voir comment chaque itération qualifiée et ajoutée au niveau de hiérarchie précédent a été appliquée...

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