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

痴心易碎 提交于 2019-12-17 17:02:52

问题


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

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

I need to write a query that will generate all paths that lead to a given Node.

Lets say it I have the following tree:

A
-B
--C
-D
--C

Which would be stored as:

NULL | A
A    | B
A    | D
B    | C
D    | C

When asking for the Paths for C, I would like to get back two paths (written more or less like this):

A > B > C,
A > D > C

回答1:


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



回答2:


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;



回答3:


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;


来源:https://stackoverflow.com/questions/14241936/how-can-i-generate-a-hierarchy-path-in-sql-that-leads-to-a-given-node

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!