How can I generate a hierarchy path in SQL that leads to a given node?

后端 未结 3 909
不思量自难忘°
不思量自难忘° 2020-12-07 03:24

In my MS SQL 2008 R2 database I have this table:

TABLE [Hierarchy]
[ParentCategoryId] [uniqueidentifier] NULL,
[ChildCategoryId] [uniqueidentifier] NOT NULL         


        
相关标签:
3条回答
  • 2020-12-07 03:47

    Here is my solution, Sql Fiddle

    DECLARE @child VARCHAR(10) = 'C'
    
        ;WITH children AS
        (
    
           SELECT 
             ParentCategoryId,
            CAST(ISNULL(ParentCategoryId + '->' ,'')  + ChildCategoryId AS VARCHAR(4000)) AS Path
           FROM Hierarchy
           WHERE ChildCategoryId =  @child
         UNION ALL
           SELECT 
             t.ParentCategoryId,
             list= CAST(ISNULL(t.ParentCategoryId  + '->' ,'')  + d.Path AS VARCHAR(4000))
           FROM Hierarchy t
           INNER JOIN children  AS d
                ON t.ChildCategoryId = d.ParentCategoryId
         )
    
        SELECT Path 
        from children c
        WHERE ParentCategoryId IS NULL
    

    Output:

    A->D->C 
    A->B->C 
    

    UPDATE:

    @AlexeiMalashkevich, to just get id, you may try this

    SQL Fiddle

    DECLARE @child VARCHAR(10) = 'C'
    
    ;WITH children AS
    (
    
       SELECT 
         ParentCategoryId,
         ChildCategoryId  AS Path
       FROM Hierarchy
       WHERE ChildCategoryId =  @child
     UNION ALL
       SELECT 
         t.ParentCategoryId,
         d.ParentCategoryId 
       FROM Hierarchy t
       INNER JOIN children  AS d
            ON t.ChildCategoryId = d.ParentCategoryId
     )
    
    SELECT DISTINCT PATH
    from children c
    
    0 讨论(0)
  • 2020-12-07 03:55

    Possible solution is to use recursive CTE as mentioned by @a_horse_with_no_name:

    CREATE TABLE [Hierarchy](
    [ParentCategoryId] CHAR(1) NULL,
    [ChildCategoryId] CHAR(1) NOT NULL
    );
    
    
    INSERT INTO Hierarchy
    SELECT NULL, 'A' UNION ALL
    SELECT 'A', 'B' UNION ALL
    SELECT 'A', 'D' UNION ALL
    SELECT 'B', 'C' UNION ALL
    SELECT 'D', 'C';
    
    
    WITH CTE AS (
        SELECT 
            ParentCategoryId, ChildCategoryId, 
            CAST(ISNULL(ParentCategoryId,'') + ChildCategoryId AS VARCHAR(255)) [Path] 
        FROM Hierarchy
        WHERE ParentCategoryId IS NULL
    
        UNION ALL
    
        SELECT 
            H.ParentCategoryId, H.ChildCategoryId, 
            CAST(C.[Path] + ' > ' + H.ChildCategoryId AS VARCHAR(255)) [Path] 
        FROM Hierarchy H
        INNER JOIN CTE C ON C.ChildCategoryId = H.ParentCategoryId
    ) SELECT * FROM CTE;
    
    0 讨论(0)
  • 2020-12-07 03:57

    That's an interesting hierarchy structure. Seems to allow for parents to possibly be children of their children. If this were to happen this code logic would break, but as long as that doesn't occur this should work.

    Create  Function dbo.IdentifyHierarchyPaths (@DeepestChildNode UniqueIdentifier)
    Returns @hierarchy Table
    (
            Hierarchy Varchar(Max)
    )
    As
    Begin
            ;With   BuildHier As
            (
                    Select  Convert(Varchar(Max),h2.ChildCategoryId) As child, Convert(Varchar(Max),h1.ChildCategoryId) + ' > ' +  Convert(Varchar(Max),h2.ChildCategoryId) As hier
                    From    Hierarchy h1
                    Left    Join Hierarchy h2
                            On  h1.ChildCategoryId = h2.ParentCategoryId
                    Where   h1.ParentCategoryId Is Null
                    Union   All
                    Select  Convert(Varchar(Max),h1.ChildCategoryId) As child, bh.hier + ' > ' +  Convert(Varchar(Max),h1.ChildCategoryId) As hier
                    From    BuildHier bh
                    Join    Hierarchy h1
                            On  bh.child = h1.ParentCategoryId
            ),      HierWithTopLevel As
            (
                    Select  Convert(Varchar(Max),ChildCategoryId) As hierarchy
                    From    Hierarchy
                    Where   ParentCategoryId Is Null
                    Union   
                    Select  hier
                    From    BuildHier
            )
            Insert  @hierarchy
            Select  hierarchy
            From    HierWithTopLevel
            Where   Right(hierarchy,36) = Convert(Varchar(36),@DeepestChildNode);
            Return;
    End;
    
    0 讨论(0)
提交回复
热议问题