【问题标题】:Need to get descendent items list in stored procedure需要在存储过程中获取后代项目列表
【发布时间】:2011-11-09 17:25:50
【问题描述】:

说明:

有一个表由两列(ParentId 和 ChildId)组成,显示一些实体的层次结构。每个 Id 只能在 ParentId 列中显示一次。这意味着每个实体只有一个子实体。

问题:我需要检查实体(其 Id)是否在父实体的后代列表中。

【问题讨论】:

  • 你在做周期检测吗?
  • ParentID 是否有唯一约束?
  • ParentId 和 ChildId 对是唯一约束。但表中没有其他约束。

标签: sql sql-server-2008 tsql stored-procedures hierarchy


【解决方案1】:
DECLARE @parentId INT
DECLARE @childId INT
DECLARE @targetChildId INT
SET @targetChildId=<put id of a child you want to find>
SET @parentId=<put id of a parent you are looking child for>
SET @childId=0

WHILE (@childId<>@targetChildId)
    BEGIN
        IF(EXISTS(SELECT ChildId FROM Hierarchies WHERE ParentId=@parentId))
        BEGIN
            SET @childId=(SELECT ChildId FROM Hierarchies WHERE ParentId=@parentId)
            SET @parentId=@childId
        END 
        ELSE
        BEGIN
            SET @childId=0
            BREAK
        END
    END
PRINT @childId

如果在目标父级中找不到目标子级,则返回 0。

【讨论】:

    【解决方案2】:

    样本数据:

    CREATE TABLE [dbo].[EntityHierarchy]
    (
        [EntityId] INT,
        [ChildEntityId] INT
    )
    
    INSERT  [dbo].[EntityHierarchy]
    VALUES  (1, 2),
            (2, 3),
            (3, 4),
            (4, 1) -- Cycle
    

    寻找循环关系:

    DECLARE @SearchEntityId INT = 1
    
    ;WITH [cteRursive] AS
    (
        SELECT  1 AS [ROW_NUMBER],
                [ChildEntityId] AS [EntityId]
        FROM [dbo].[EntityHierarchy]
        WHERE [EntityId] = @SearchEntityId
        UNION ALL
        SELECT  r.[ROW_NUMBER] + 1,
                h.[ChildEntityId]
        FROM [cteRursive] r
        INNER JOIN [dbo].[EntityHierarchy] h 
            ON r.[EntityId] = h.[EntityId]
        WHERE h.[ChildEntityId] <> @SearchEntityId
    )
    SELECT h.*
    FROM [cteRursive] r
    INNER JOIN [dbo].[EntityHierarchy] h 
        ON r.[EntityId] = h.[EntityId]
    WHERE r.[ROW_NUMBER] = (SELECT MAX([ROW_NUMBER]) FROM [cteRursive])
    

    我使用recursive CTE 列出后代。最后一个后代的 child 要么创建循环,要么不创建循环。

    【讨论】:

    • 很好指点,但我只需要检查 ChildId 是否在 ParentId 的后代列表中。没有任何循环。
    • 我对这个 CTE 进行了一些更新,它工作正常。正是我想要的。
    猜你喜欢
    • 1970-01-01
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 2023-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多