获取层次结构数据直到最后一个孩子-SQL Server

时间:2018-08-10 15:06:37

标签: sql sql-server join hierarchical-data

我有这个表结构。我想创建一个查询分层数据的查询,直到最后一个孩子为止,而不再引用父对象。

表结构:

    ParentId    ChildId
    -------------------
    NULL        6000101
    6000101     6000102
    6000101     6000106
    6000101     6000107
    6000102     6000103
    6000102     6000104
    6000102     6000105
    6000103     6000101
    6000104     6000101
    6000105     6000101
    6000106     6000101
    6000106     6000102
    6000107     6000102
    6000107     6000105

Current data structure image

所需的结构或结果集:

    ParentId  ChildId 
    ---------------------
    NULL      6000101
    6000101   6000102
    6000101   6000106
    6000101   6000107
    6000102   6000103
    6000102   6000104
    6000102   6000105

Desired result Image

有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

通常,查询层次结构时会使用递归公用表表达式,但是由于数据中有循环引用,因此需要使用循环。

假设您的源表称为“ MyTable”。您将要创建一个表(临时表或其他表),该表将保存清理后的层次结构:

create table MyHierarchy (
  ParentId int null
  ,ChildId int not null
  ,[Level] int not null
);

然后,您将输入根父记录并循环直到找到循环引用:

-- insert root parent record
insert into MyHierarchy
select
    *
    ,0 as [Level]
from
    MyTable
where
    ParentId is null;

-- loop until you reach a circular reference
while @@ROWCOUNT > 0
begin
    insert into MyHierarchy
    select
        MyTable.*
        ,MyHierarchy.[Level] + 1 as [Level]
    from
        MyTable
        inner join
        MyHierarchy on MyTable.ParentId = MyHierarchy.ChildId
    where
        MyTable.ChildId not in (select ChildId from MyHierarchy)
end

这几乎可以帮助您。您有一个记录(ChildId = 6000105)引用了多个父母。偏向较低层次,您现在可以将row_number()函数与cte一起使用,以获得唯一的关系。

with cte as (
    select
        MyHierarchy.*
        ,ROW_NUMBER() OVER(PARTITION BY MyHierarchy.ChildId ORDER BY parent.[Level], MyHierarchy.parentId) as RowNumber
    from
        MyHierarchy
        left join
        MyHierarchy parent on MyHierarchy.ParentId = parent.ChildId
)
select
    *
from
    cte
where
    RowNumber = 1
order by
    ParentId
    ,ChildId

http://sqlfiddle.com/#!18/7089d/3