SQL Server CTE -Find top parentID forEach childID?

后端 未结 9 1075
Happy的楠姐
Happy的楠姐 2020-12-08 08:24

I have a table which contains hierarchy data - something like:

childID  |  parentID
____________________
  1      |     5
  5      |     9
  9      |     20         


        
相关标签:
9条回答
  • 2020-12-08 09:03
    With cteherarchy as 
    (
    Select ChileId,Name,ParentId from tblHerarchy
    where ParentId is null 
    union ALL
    Select h.ChileId,h.Name,h.ParentId  from cte
    inner join tblHerarchy h on h.ParentId=cte.ChileId
    ) 
    Select * from cteherarchy 
    
    0 讨论(0)
  • 2020-12-08 09:07

    Can't you do something like this?

    ;WITH cte AS (....)
    SELECT
        * 
    FROM 
        cte
    CROSS APPLY 
        dbo.myTable tbl ON cte.XXX = tbl.XXX
    

    Put the CROSS APPLY after the CTE definition - into the one SQL statement that refers back to the CTE. Wouldn't that work??

    OR: - flip around your logic - do a "top-down" CTE, that picks the top-level nodes first, and then iterates through the hiearchy. This way, you can easily determine the "top-level father" in the first part of the recursive CTE - something like this:

    ;WITH ChildParent AS
    (
        SELECT
            ID,
            ParentID = ISNULL(ParentID, -1),
            SomeName, 
            PLevel = 1,   -- defines level, 1 = TOP, 2 = immediate child nodes etc.
            TopLevelFather = ID  -- define "top-level" parent node
        FROM dbo.[Agent_Agents] 
        WHERE ParentID IS NULL
    
        UNION ALL
    
        SELECT
            a.ID,
            ParentID = ISNULL(a.ParentID, -1),
            a.SomeName, 
            PLevel = cp.PLevel + 1,
            cp.TopLevelFather   -- keep selecting the same value for all child nodes
        FROM dbo.[Agent_Agents] a
        INNER JOIN ChildParent cp ON r.ParentID = cp.ID
    )
    SELECT  
       ID,
       ParentID,
       SomeName,
       PLevel,
       TopLevelFather   
    FROM ChildParent
    

    This would give you nodes something like this (based on your sample data, slightly extended):

    ID  ParentID  SomeName      PLevel  TopLevelFather
    20    -1      Top#20           1          20
     4    -1      TOP#4            1           4
     8    -1      TOP#8            1           8
     7     8      ChildID = 7      2           8
     3     7      ChildID = 3      3           8
     2     4      ChildID = 2      2           4
     9    20      ChildID = 9      2          20
     5     9      ChildID = 5      3          20
     1     5      ChildID = 1      4          20
    

    Now if you select a particular child node from this CTE output, you'll always get all the infos you need - including the "level" of the child, and its top-level parent node.

    0 讨论(0)
  • 2020-12-08 09:07

    I have not yet the time to look further into your question and am not sure whether or not i've understood your problem, but couldn't you use this svf to get the top father's id?

    CREATE FUNCTION [dbo].[getTopParent] (
        @ChildID INT
    )
    
    RETURNS int
    AS
    BEGIN
        DECLARE @result int;
        DECLARE @ParentID int;
    
        SET @ParentID=(
            SELECT ParentID FROM ChildParent
            WHERE ChildID = @ChildID 
        )
    
        IF(@ParentID IS NULL)
            SET @result = @ChildID 
        ELSE
            SET @result = [dbo].[getTopParent](@ParentID)
    
        RETURN @result    
    END
    

    Then you should be able to find each top parent in this way:

    SELECT ChildID
        ,  [dbo].[getTopParent](ChildID) AS TopParentID
    FROM ChildParent
    
    0 讨论(0)
提交回复
热议问题