【问题标题】:Parent child relation hierarchy (multiple children) - SQL Server父子关系层次结构(多个子级) - SQL Server
【发布时间】:2018-08-14 13:26:53
【问题描述】:

我有一个包含多个子父关系的表。我想得到一个分层数据集。

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

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

【问题讨论】:

  • 你能分享你写的代码,发现不能解决问题吗?
  • 选择 tWrkflw.otcID, ISNULL(tWrkflwArrow.osoObjectTemplateProcessStepBeginning_otsID,0) 作为 PARENTID, ISNULL(tWrkflwArrow.osoObjectTemplateProcessStepEnding_otsID,0) 作为 CHILDID, ISNULL(tWrkflwStop.otsInternalName,tWrkflwStoponeFROMEx ABC AS tWrkflw INNER JOIN DEF AS tWrkflwStop ON tWrkflwStop.otsObjectTemplateCategory_otcID = tWrkflw.otcID INNER JOIN [GHI AS tWrkflwArrow ON tWrkflwArrow.osoObjectTemplateProcessStepEnding_otsID = tWrkflwStop3WHERE5000f>
  • 您应该使用您尝试过的代码更新您的问题。注释对于代码来说是可怕的。
  • 你怎么知道像 1004 这样的循环引用的哪个分支要省略?如果返回到较低编号参考的编号较高的参考是要忽略/删除的参考,那么这样做会相对容易,但这是否正确,或者是否有一些其他标准需要检查哪些参考应被视为主要参考?
  • 您寻求的答案可以在这里找到。 spaghettidba.com/2015/04/24/…

标签: sql-server join hierarchical-data


【解决方案1】:

这是解决问题的一种方法。我敢肯定还有更好的。

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;

【讨论】:

  • 好的。让我试试看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多