sql >> Database teknologi >  >> RDS >> Mysql

Forespørgsel om at få overordnede poster med underordnet post, efterfulgt af næste overordnede-underordnede poster i mysql

Den løsning, jeg foreslår her, bruger begrebet materialiseret vej. Følgende er et eksempel på materialiserede stier, der bruger dine eksempeldata. Jeg håber, det hjælper dig med at forstå materialiseret vejkoncept:

+----+--------------------------+----------+------------------+ | ID | Name | ParentID | MaterializedPath | +----+--------------------------+----------+------------------+ | 1 | Parent 1 | 0 | 1 | | 2 | Parent 2 | 0 | 2 | | 4 | Parent 2 Child 1 | 2 | 2.4 | | 6 | Parent 2 Child 1 Child 1 | 4 | 2.4.6 | | 7 | Parent 2 Child 1 Child 2 | 4 | 2.4.7 | | 3 | Parent 1 Child 1 | 1 | 1.3 | | 5 | Parent 1 Child 1 Child | 3 | 1.3.5 | +----+--------------------------+----------+------------------+

Hver node N har en materialiseret sti, fortæller denne sti dig vejen fra rodknudepunktet til knudepunktet N . Det kan bygges sammen med node-id'erne. For eksempel for at nå node 5 startende fra dens rodknude, besøger du node 1 , node 3 , og node 5 , så node 5 materialiseret sti er 1.3.5

Tilfældigvis kan den rækkefølge, du leder efter, opnås ved den materialiserede vej.

I det foregående eksempel er materialiserede stier konkatenerende strenge, men jeg foretrækker binær sammenkædning af en række årsager.

For at bygge de materialiserede stier har du brug for følgende rekursive CTE:

CREATE TABLE Tree
(
    ID int NOT NULL CONSTRAINT PK_Tree PRIMARY KEY, 
    Name nvarchar(250) NOT NULL,
    ParentID int NOT NULL,
)

INSERT INTO Tree(ID, Name, ParentID) VALUES
(1, 'Parent 1', 0),
(2, 'Parent 2', 0),
(3, 'Parent 1 Child 1', 1),
(4, 'Parent 2 Child 1', 2),
(5, 'Parent 1 Child 1 Child', 3),
(6, 'Parent 2 Child 1 Child 1', 4),
(7, 'Parent 2 Child 1 Child 2', 4)

GO
WITH T AS
(
    SELECT
        N.ID, N.Name, N.ParentID, CAST(N.ID AS varbinary(512)) AS MaterializedPath
    FROM
        Tree N
    WHERE
        N.ParentID = 0

    UNION ALL

    SELECT
        N.ID, N.Name, N.ParentID, CAST( T.MaterializedPath + CAST(N.ID AS binary(4)) AS varbinary(512) ) AS MaterializedPath
    FROM
        Tree N INNER JOIN T
            ON N.ParentID = T.ID

)
SELECT *
FROM T
ORDER BY T.MaterializedPath
 

Resultat:

+----+--------------------------+----------+----------------------------+ | ID | Name | ParentID | MaterializedPath | +----+--------------------------+----------+----------------------------+ | 1 | Parent 1 | 0 | 0x00000001 | | 3 | Parent 1 Child 1 | 1 | 0x0000000100000003 | | 5 | Parent 1 Child 1 Child | 3 | 0x000000010000000300000005 | | 2 | Parent 2 | 0 | 0x00000002 | | 4 | Parent 2 Child 1 | 2 | 0x0000000200000004 | | 6 | Parent 2 Child 1 Child 1 | 4 | 0x000000020000000400000006 | | 7 | Parent 2 Child 1 Child 2 | 4 | 0x000000020000000400000007 | +----+--------------------------+----------+----------------------------+

Ovenstående rekursive CTE starter med rodknuderne. At beregne den materialiserede sti for en rodknude er trivielt ligetil, det er selve knudepunktets ID. Ved næste iteration forbinder CTE rodknudepunkter med sine underknuder. Den materialiserede sti til en underordnet node CN er sammenkædningen af ​​den materialiserede sti til dens overordnede node PN og id'et for noden CN . Efterfølgende iterationer går et niveau ned på træet, indtil bladknuderne er nået.




  1. Hvordan tilføjes en ny kolonne til MYSQL-tabellen?

  2. Min MySQL-database er beskadiget... Hvad gør jeg nu?

  3. Hvordan finder man det aktuelle transaktionsniveau?

  4. Behandling af store mængder data i PHP uden browser-timeout