sql >> Base de Datos >  >> RDS >> Mysql

Salida MYSQL en formato de árbol O nivel de adición (padre-hijo)

Aunque no puede hacerlo con una sola consulta, puede hacerlo con un procedimiento almacenado ... El único requisito previo es que debe agregar 2 registros más a su tabla de muestra existente para representar que "C1" y "C2" SON el nivel superior... Agregue un registro donde el campo "Principal" esté en blanco, y el nivel secundario sea "C1" y otro para "C2". Esto "preparará" el nivel principal superior. para la asociación de jerarquía posterior, de lo contrario no tiene "base" inicial de la jerarquía de nivel superior. También requiere una columna de "clave principal" (que he creado en este script como "IDMyTable", que es solo secuencial 1-x, pero supondría que tiene una columna de incremento automático en su tabla para usar en su lugar).

Incluí todas las columnas de salida para mostrar CÓMO se construye, pero la premisa de esta rutina es crear una tabla basada en las salidas de columna esperadas, pero extra para mantener la representación jerárquica aguas abajo a medida que se construye. Para ASEGURARME de que conserven la orientación correcta a medida que las capas se hacen más profundas, estoy concatenando la columna "ID". Verá cómo funciona en el conjunto de resultados final.

Luego, en el conjunto de resultados final, estoy rellenando previamente los espacios en función de la profundidad de los datos de la jerarquía.

El ciclo agregará cualquier registro en función de que su padre se encuentre en el conjunto de resultados anterior, pero solo si la ID aún no se ha agregado (evitar duplicados)...

Para ver cómo se agregó constantemente el orden cíclico, puede ejecutar la última consulta SIN el orden y ver cómo se calificó cada iteración y se agregó el nivel de jerarquía anterior...

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