簡體   English   中英

查詢以獲取具有子記錄的父記錄,然后是mysql中的下一個父子記錄

[英]Query to get parent records with child record, followed by next parent-child records in mysql

我在數據庫的Names表中有以下格式的數據:

ID  | Name                     | ParentID
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

ParentID列將ID列中的數據作為父記錄。 帶有0值的ParentID表示根項。 我需要編寫一個查詢來按以下順序獲取數據:

ID  | Name                     | ParentID
1   | Parent 1                 | 0
3   | Parent 1 Child 1         | 1
5   | Parent 1 Child 1 Child   | 3
2   | Parent 2                 | 0
4   | Parent 2 Child 1         | 2    
6   | Parent 2 Child 1 Child 1 | 4
7   | Parent 2 Child 1 Child 2 | 4

我需要獲取根記錄( ParentID為0的記錄),然后是該根記錄的所有child sub-children記錄,然后獲取下一個根記錄,然后是該根記錄的child記錄和sub-children記錄,依此類推。

我在這里提出的解決方案使用了物化路徑的概念。 以下是使用示例數據的物化路徑示例。 我希望它能幫助您理解物化路徑概念:

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

每個節點N都有一個物化路徑,該路徑告訴您從​​根節點到節點N路徑。 它可以構建連接節點id。 例如,要從其根節點開始到達節點5 ,請訪問節點1 ,節點3和節點5 ,因此節點5物化路徑為1.3.5

巧合的是,您正在尋找的訂單可以通過物化路徑實現訂購。

在前面的示例中,物化路徑是buit連接字符串,但出於多種原因,我更喜歡二進制連接。

要構建物化路徑,您需要以下遞歸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

結果:

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

上述遞歸CTE以根節點開始。 計算根節點的物化路徑非常簡單,它是節點本身的ID。 在下一次迭代中,CTE將根節點與其子節點連接起來。 子節點CN的物化路徑是其父節點PN的物化路徑和節點CN的id的串聯。 隨后的迭代在樹上向下推進一級,直到到達葉節點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM