sql >> Databasteknik >  >> RDS >> Mysql

MYSQL-utdata i trädformat ELLER Lägger till nivå (förälder-barn)

Även om du inte kan göra med en enda fråga, kan du göra med en lagrad procedur... Det enda förhandskravet, du måste lägga till ytterligare 2 poster till din befintliga exempeltabell för att representera att "C1" och "C2" ÄR den översta nivån... Lägg till en post där "Förälder"-fältet är tomt, och den underordnade nivån är "C1" och en annan för "C2". Detta kommer att "förbereda" den översta föräldranivån. för efterföljande hierarkiassociation, annars har du ingen start "bas" för toppnivåhierarkin. Det kräver också en kolumn "primärnyckel" (som jag har skapat i det här skriptet som "IDMyTable" som bara är 1x sekventiell, men skulle anta att du har en kolumn för automatisk ökning av tabellen att använda istället).

Jag har inkluderat alla utdatakolumner för att visa HUR den är byggd, men förutsättningen för denna rutin är att skapa en tabell baserad på förväntade kolumner, men extra för att hålla den hierarkiska representationen nedströms när den byggs. För att säkerställa att de behåller rätt orientering när lagren blir djupare, sammanfogar jag kolumnen "ID" -- du kommer att se hur det fungerar i den slutliga resultatuppsättningen.

Sedan, i den slutliga resultatuppsättningen, förutfyller jag mellanslag baserat på hur djup hierarkidatan är.

Slingan kommer att lägga till alla poster baserat på att deras överordnade hittas i föregående resultatuppsättning, men bara om ID:t inte redan har lagts till (förhindra dubbletter)...

För att se hur den cykliska ordningen ständigt lades till kan du köra den sista frågan UTAN ordningen av och se hur varje iteration kvalificerade sig och lade till den tidigare hierarkinivån...

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


  1. Hur du vårrensar din databas

  2. php:snabbaste sättet att generera ett 5-siffrigt nummer som inte redan finns i MySQL db-kolumnen (med ett unikt attribut)

  3. Design för att representera anställdas in- och utcheckning

  4. MySQL-kompatibilitet med MacOS Sierra