sql >> Databáze >  >> RDS >> Mysql

Dotaz na získání rodičovských záznamů s podřízeným záznamem, následovaný dalšími záznamy rodič-dítě v mysql

Řešení, které zde navrhuji, využívá koncept zhmotněné cesty. Následuje příklad materializovaných cest pomocí vašich ukázkových dat. Doufám, že vám to pomůže pochopit koncept materializované cesty:

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

Každý uzel N má zhmotněnou cestu, tato cesta vám říká, jak jít z kořenového uzlu do uzlu N . Může být sestaven zřetězením ID uzlů. Chcete-li například dosáhnout uzlu 5 počínaje jeho kořenovým uzlem navštívíte uzel 1 , uzel 3 a uzel 5 , takže uzel 5 materializovaná cesta je 1.3.5

Shodou okolností lze zakázku, kterou hledáte, dosáhnout uspořádáním zhmotněnou cestou.

V předchozím příkladu jsou materializované cesty vytvořeny zřetězením řetězců, ale já dávám přednost binárnímu zřetězení z mnoha důvodů.

K sestavení materializovaných cest potřebujete následující rekurzivní 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

Výsledek:

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

Výše uvedený rekurzivní CTE začíná kořenovými uzly. Výpočet materializované cesty pro kořenový uzel je triviálně přímočarý, jde o ID samotného uzlu. Při další iteraci CTE spojí kořenové uzly se svými podřízenými uzly. Zhmotněná cesta pro podřízený uzel CN je zřetězení materializované cesty jeho nadřazeného uzlu PN a id uzlu CN . Následující iterace postupují ve stromu o jednu úroveň dolů, dokud nedosáhnete listových uzlů.




  1. Systém správy relačních databází (RDBMS):MSSQL vs MySQL

  2. Příklad externí tabulky Oracle

  3. Pomocí ORDER BY a GROUP BY společně

  4. počítejte rozdíl data v hodinách pomocí php a mysql