父子关系层次结构(多个子)-SQL Server

时间:2018-08-13 15:26:42

标签: sql-server join hierarchical-data

我有一个具有多个子父母关系的表。我想要一个分层数据集。

表结构。 (包括循环引用)

Parent   Child1 Child2
--====== ======== ========
0        1000     NULL
1000     1001     NULL
1001     1002     1003
1002     1004     1005
1003     1005     NULL
1004     1002     NULL
1005     1006     NULL

我想要的数据集是(Child2-1003&1005成为父母,因为他们有他们的孩子,但直到最后一个孩子-没有像Child1-1004这样的循环[仅保留孩子])

Parent   Child
--====== ======== 
0        1000
1000     1001
1001     1002
1002     1003
1002     1004
1003     1005
1005     1006

有人可以帮忙吗?

我尝试了以下代码-

INSERT INTO @WorkflowStop (ParentId, ChildId,AdvChild, StopName)
                SELECT ISNULL(tWrkflwArrow.osoObjectTemplateProcessStepBeginning_otsID,0) AS ParentId,
                       ISNULL(tWrkflwArrow.osoObjectTemplateProcessStepEnding_otsID,0) AS ChildId,
                       ISNULL(tWrkflwArrow.osoObjectTemplateProcessStepAutoAdvance_otsID,0) AS AdvChild,
                       ISNULL(tWrkflwStop.otsInternalName,tWrkflwStop.otsExternalName) AS StopName
                FROM ABC.[dbo].[Workflow] AS tWrkflw
                INNER JOIN DEF AS tWrkflwStop
                    ON tWrkflwStop.otsObjectTemplateCategory_otcID = tWrkflw.otcID
                INNER JOIN GHI AS tWrkflwArrow
                    ON tWrkflwArrow.osoObjectTemplateProcessStepEnding_otsID = tWrkflwStop.otsID
                WHERE tWrkflw.otcID = @WorkflowDefinitionId 

                INSERT into @WorkflowStopHierarchy (ParentId, ChildId,AdvChild, StopName,[Level])
                SELECT tWrkflwStop.ParentId,
                       tWrkflwStop.ChildId,
                       tWrkflwStop.AdvChild,
                       tWrkflwStop.StopName,
                       0 as [Level]
                FROM @WorkflowStop AS tWrkflwStop
                WHERE tWrkflwStop.ParentId = 0;

                WHILE @@ROWCOUNT > 0
                BEGIN
                    INSERT INTO @WorkflowStopHierarchy (ParentId, ChildId,AdvChild, StopName,[Level])
                    SELECT tWrkflwStop.ParentId,
                           tWrkflwStop.ChildId,
                           tWrkflwStop.AdvChild,
                           tWrkflwStop.StopName,
                           tHierarchy.[Level] + 1 as [Level]
                    FROM @WorkflowStop AS tWrkflwStop
                    INNER JOIN @WorkflowStopHierarchy AS tHierarchy
                         ON (tWrkflwStop.ParentId = tHierarchy.ChildId) OR (tWrkflwStop.ParentId = tHierarchy.AdvChild)
                    WHERE (tWrkflwStop.ChildId NOT IN (select ChildId from @WorkflowStopHierarchy)) OR (tWrkflwStop.AdvChild NOT IN (select AdvChild from @WorkflowStopHierarchy))
                END;

                WITH CTE AS 
                (
                    SELECT tHierarchyChild.ParentId,
                           tHierarchyChild.ChildId,
                           tHierarchyChild.StopName,
                           ROW_NUMBER() OVER(PARTITION BY tHierarchyChild.ChildId ORDER BY tHierarchyParent.[Level], tHierarchyChild.parentId) as RowNumber
                    FROM @WorkflowStopHierarchy AS tHierarchyChild
                    LEFT JOIN @WorkflowStopHierarchy AS tHierarchyParent 
                        ON tHierarchyChild.ParentId = tHierarchyParent.ChildId
                )


                SELECT @WorkflowDefinitionId,
                       ParentId,
                       ChildId,
                       StopName
                FROM CTE
                WHERE RowNumber = 1
                ORDER BY ParentId,ChildId

1 个答案:

答案 0 :(得分:0)

这是解决它的一种方法。我敢肯定会有更好的。

drop table if exists #data;

create table #data(
    parent nvarchar(100) ,
    child1 nvarchar(100) ,
    child2 nvarchar(100)
);

insert  #data
values  ('0', '1000', null),
        ('1000', '1001', null),
        ('1001', '1002', '1003'),
        ('1002', '1004', '1005'),
        ('1003', '1005', null),
        ('1004', '1002', null),
        ('1005', '1006', null);

drop table if exists #paths;
select parent, child1 as child into #paths from #data where child1 is not null
union
select parent, child2 from #data where child2 is not null;

drop table if exists #results;
create table #results(parent nvarchar(100), child nvarchar(100));
insert  #results 
select  parent, child 
from    #paths 
where   parent not in (select child from #paths);
while @@rowcount > 0
    insert  #results 
    select  parent, child 
    from    #paths 
    where   parent not in (select parent from #results) 
            and child not in (select parent from #results) 
            and parent in (select child from #results);
select * from #results;