【问题标题】:Query to get parent records with child record, followed by next parent-child records in mysql查询以获取带有子记录的父记录,然后是mysql中的下一个父子记录
【发布时间】:2015-03-11 05:30:30
【问题描述】:

我在数据库的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 列的数据作为父记录。 ParentID0 值表示根项目。我需要编写一个查询以按以下顺序获取数据:

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 的记录),然后是该根记录的所有 childsub-children,然后获取下一个根记录,然后是 childsub-children这个根记录等等。

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    我在这里提出的解决方案使用了物化路径的概念。以下是使用示例数据的具体化路径示例。希望对您理解物化路径概念有所帮助:

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

    巧合的是,你要找的顺序可以通过物化路径来实现排序。

    在前面的示例中,物化路径是连接字符串,但出于多种原因,我更喜欢二进制连接。

    要构建物化路径,您需要以下递归 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 的串联。随后的迭代在树上向下推进一级,直到到达叶节点。

    【讨论】:

      猜你喜欢
      • 2014-07-14
      • 1970-01-01
      • 2019-02-21
      • 1970-01-01
      • 1970-01-01
      • 2016-04-16
      • 2021-02-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多