SQL Server: How to limit CTE recursion to rows just recursivly added?

前端 未结 8 1123
北海茫月
北海茫月 2020-12-08 23:12

Simpler Example

Let\'s try a simpler example, so people can wrap their heads around the concepts, and have a practical example that you can copy&paste into SQL

8条回答
  •  执笔经年
    2020-12-08 23:31

    Have you tried constructing a path in the CTE and using it to identify ancestors?

    You can then subtract the descendant node depth from the ancestor node depth to calculate the GenerationsRemoved column, like so...

    DECLARE @Nodes TABLE
    (
        NodeId varchar(50) PRIMARY KEY NOT NULL,
        ParentNodeId varchar(50) NULL
    )
    
    INSERT INTO @Nodes (NodeId, ParentNodeId) VALUES ('A', NULL)
    INSERT INTO @Nodes (NodeId, ParentNodeId) VALUES ('B', 'A')
    INSERT INTO @Nodes (NodeId, ParentNodeId) VALUES ('C', 'B')
    
    DECLARE @Hierarchy TABLE
    (
        NodeId varchar(50) PRIMARY KEY NOT NULL,
        ParentNodeId varchar(50) NULL,
        Depth int NOT NULL,
        [Path] varchar(2000) NOT NULL
    )
    
    WITH Hierarchy AS
    (
        --initialization
        SELECT NodeId, ParentNodeId, 0 AS Depth, CONVERT(varchar(2000), NodeId) AS [Path]
        FROM @Nodes
        WHERE ParentNodeId IS NULL
    
        UNION ALL
    
        --recursive execution
        SELECT n.NodeId, n.ParentNodeId, p.Depth + 1, CONVERT(varchar(2000), p.[Path] + '/' + n.NodeId)
        FROM Hierarchy AS p
        INNER JOIN @Nodes AS n
        ON p.NodeId = n.ParentNodeId
    )
    INSERT INTO @Hierarchy
    SELECT *
    FROM Hierarchy
    
    SELECT parent.NodeId AS AncestorNodeId, child.NodeId AS DescendantNodeId, child.Depth - parent.Depth AS GenerationsRemoved
    FROM @Hierarchy AS parent
    INNER JOIN @Hierarchy AS child
    ON child.[Path] LIKE parent.[Path] + '/%'
    

提交回复
热议问题