Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Saída MYSQL em formato de árvore OU Adicionando nível (pai-filho)


Embora você não possa fazer com uma única consulta, você pode fazer com um procedimento armazenado... O único pré-requisito, você precisa adicionar mais 2 registros à sua tabela de amostra existente para representar que "C1" e "C2" SÃO o nível superior... Adicione um registro onde o campo "Pai" esteja em branco, e o nível filho seja "C1" e outro para "C2". Isso "preparará" o nível pai mais alto. para associação de hierarquia subsequente, caso contrário, você não tem "base" inicial da hierarquia de nível superior. Ele também requer uma coluna de "chave primária" (que eu criei neste script como "IDMyTable", que é apenas 1-x sequencial, mas suponha que você tenha uma coluna de incremento automático em sua tabela para usar).

Incluí todas as colunas de saída para mostrar COMO ele é construído, mas a premissa dessa rotina é criar uma tabela com base nas saídas de coluna esperadas, mas extra para manter a representação hierárquica downstream à medida que está sendo construída. Para GARANTIR que eles mantenham a orientação correta à medida que as camadas se aprofundam, estou concatenando a coluna "ID" - você verá como funciona no conjunto de resultados final.

Então, no conjunto de resultados final, estou pré-preenchendo os espaços com base na profundidade dos dados da hierarquia.

O loop adicionará todos os registros com base em seu pai encontrado no conjunto de resultados anterior, mas somente se o ID ainda não tiver sido adicionado (evitar duplicatas)...

Para ver como a ordem cíclica foi constantemente anexada, você pode executar a última consulta SEM a ordem e ver como cada iteração qualificada e adicionada ao nível de hierarquia anterior foi aplicada...
-- --------------------------------------------------------------------------------
-- 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