我有这个表结构。我想创建一个查询分层数据的查询,直到最后一个孩子为止,而不再引用父对象。
表结构:
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
所需的结构或结果集:
ParentId ChildId
---------------------
NULL 6000101
6000101 6000102
6000101 6000106
6000101 6000107
6000102 6000103
6000102 6000104
6000102 6000105
有人可以帮忙吗?
答案 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