sql >> Databasteknik >  >> RDS >> Mysql

Fråga för att få föräldraposter med underordnade poster, följt av nästa förälder-underordnade poster i mysql

Den lösning jag föreslår här använder begreppet materialiserad väg. Följande är ett exempel på materialiserade sökvägar som använder dina exempeldata. Jag hoppas att det hjälper dig att förstå det materialiserade vägkonceptet:

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

Varje nod N har en materialiserad väg, den här vägen talar om för dig hur du ska gå från rotnoden till noden N . Det kan byggas samman med nod-id:n. Till exempel för att nå noden 5 från dess rotnod besöker du nod 1 , nod 3 och nod 5 , så nod 5 materialiserad sökväg är 1.3.5

Av en slump kan den ordning du letar efter uppnås genom den materialiserade vägen.

I det föregående exemplet är materialiserade vägar sammanlänkade strängar, men jag föredrar binär sammanlänkning av ett antal anledningar.

För att bygga de materialiserade vägarna behöver du följande rekursiva 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 |
+----+--------------------------+----------+----------------------------+

Ovanstående rekursiva CTE börjar med rotnoderna. Att beräkna den materialiserade vägen för en rotnod är trivialt okomplicerat, det är själva nodens ID. Vid nästa iteration sammanfogar CTE:n rotnoder med sina undernoder. Den materialiserade sökvägen för en underordnad nod CN är sammanlänkningen av den materialiserade sökvägen för dess överordnade nod PN och id för noden CN . Efterföljande iterationer avancerar en nivå ner på trädet tills lövnoderna nås.




  1. Villkorlig delad transformation:Exportera data från SQL Server till Oracle- och MySQL-databaser

  2. CakePHP 3 - Analysera datum med LocalStringFormat för att korrigera SQL-format och korrekt validering

  3. Hur uppdaterar man en post med sequelize för nod?

  4. Välj första raden i varje grupp i sql