排序记录,因此 children 出现在 multi-level 层次结构中的 parent 之后
Order records so children appear just after parent in a multi-level hierarchy
我有一个 table 项目,其中包含 multi-level 层次结构的所有记录。因此,有一个顶级项目,它下面有项目,而它下面又有项目,依此类推;此外,此 table.
中将有许多顶级项目
我的目标是 return 来自这个 table 的记录,这样每个 parent 后面都有其 children 的记录(这些 children 可以是以任何顺序),然后每个 children 紧随其后的是它的 children(这些 children 可以按任何顺序),依此类推。我为此创建了一个 SQLFiddle:SQLFiddle for this
我尝试使用以下查询获取此信息,但第三级层次结构项目并没有出现在它们的 parent 之后。
select Id, ParentId, ChildLevel,
CASE WHEN ChildLevel = 0 THEN Id
WHEN ChildLevel = 1 then Id
WHEN ChildLevel > 1 THEN ParentId END Num
from Items order by UltimateParentId, ChildLevel, Num ;
问题
有没有办法让 children 出现在 sql fiddle 上面的 parent 之后?
使用数据创建此 table 的脚本如下。
create table Items ( Id int , ParentId int , ChildLevel int, UltimateParentId int);
--I could have multiple hierarchy level for each top level item
--right now I am populating data at multiple levels for only one top level item
--but the table will consist of many top level items having their own hierarchy records
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (1,0,0,0);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (2,1,1,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (3,1,1,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (4,1,1,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (5,3,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (7,2,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (6,3,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (8,4,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (9,3,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (10,2,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (11,4,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (12,11,3,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (13,5,3,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (14,11,3,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (15,5,3,1);
是的。
通用 Table 表达式 (CTE) 可以递归。如果您使用 CTE,您只需要父级 IS。查看 https://technet.microsoft.com/pl-pl/library/ms186243(v=sql.105).aspx
由于您没有为 ID/Parent 使用字符串,您可以利用 hierarchyid
数据类型。
R1,R2 和 HierPath 在最后 select 是可选的。 R1 和 R2 表示所有权范围。这有助于聚合和 selection 而无需递归。
例子
;with cteP as (
Select ID
,ParentId
,HierID = convert(hierarchyid,concat('/',ID,'/'))
From Items
Where ParentId=0
Union All
Select ID = r.ID
,ParentId = r.ParentId
,HierID = convert(hierarchyid,concat(p.HierID.ToString(),r.ID,'/'))
From Items r
Join cteP p on r.ParentId = p.ID)
Select R1 = Row_Number() over (Order By HierID)
,R2 = Row_Number() over (Order By HierID) + -1 + (Select count(*) From cteP where HierID.ToString() like A.HierID.ToString()+'%')
,Lvl = HierID.GetLevel()
,ID
,ParentId
,HierID
,HierPath = HierID.GetDescendant ( null , null ).ToString()
From cteP A
Order By A.HierID
Returns
根据要求。以下可以在几秒钟内生成 200K 层
I should add... Where you see Row_Number() over (Order By ID)
I
used ID, but this can be any other field to determine the desired
presentation sequence.
例子
Select *,Lvl=1,Seq=cast(1000000+Row_Number() over (Order By ID) as varchar(900)) Into #TempBld from Items Where ParentID = 0
Declare @Cnt int=1
While @Cnt<=30
Begin
Insert Into #TempBld
Select A.*,Lvl=B.Lvl+1,Seq=B.Seq+' '+ cast(1000000+Row_Number() over (Order By A.ID) as varchar(25))
From Items A
Join #TempBld B on (B.Lvl=@Cnt and A.ParentID=B.ID)
Set @Cnt=@Cnt+1
End
Select ID,R1=cast(Row_Number() over (Order by Seq) as int),Seq Into #TempR1 From #TempBld
Create Clustered Index idx on #TempR1 (Seq)
Select A.ID,R2 = Max(B.R1) Into #TempR2 From #TempBld A Join #TempR1 B on B.Seq Like A.Seq+'%' Group By A.ID
Select B.R1
,C.R2
,A.Lvl
,A.ID
,A.ParentID
From #TempBld A
Join #TempR1 B on (A.ID=B.ID)
Join #TempR2 C on (A.ID=C.ID)
Order By 1
Returns
我有一个 table 项目,其中包含 multi-level 层次结构的所有记录。因此,有一个顶级项目,它下面有项目,而它下面又有项目,依此类推;此外,此 table.
中将有许多顶级项目我的目标是 return 来自这个 table 的记录,这样每个 parent 后面都有其 children 的记录(这些 children 可以是以任何顺序),然后每个 children 紧随其后的是它的 children(这些 children 可以按任何顺序),依此类推。我为此创建了一个 SQLFiddle:SQLFiddle for this
我尝试使用以下查询获取此信息,但第三级层次结构项目并没有出现在它们的 parent 之后。
select Id, ParentId, ChildLevel,
CASE WHEN ChildLevel = 0 THEN Id
WHEN ChildLevel = 1 then Id
WHEN ChildLevel > 1 THEN ParentId END Num
from Items order by UltimateParentId, ChildLevel, Num ;
问题
有没有办法让 children 出现在 sql fiddle 上面的 parent 之后?
使用数据创建此 table 的脚本如下。
create table Items ( Id int , ParentId int , ChildLevel int, UltimateParentId int);
--I could have multiple hierarchy level for each top level item
--right now I am populating data at multiple levels for only one top level item
--but the table will consist of many top level items having their own hierarchy records
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (1,0,0,0);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (2,1,1,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (3,1,1,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (4,1,1,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (5,3,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (7,2,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (6,3,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (8,4,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (9,3,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (10,2,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (11,4,2,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (12,11,3,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (13,5,3,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (14,11,3,1);
insert into Items (Id, ParentId, ChildLevel, UltimateParentId) values (15,5,3,1);
是的。 通用 Table 表达式 (CTE) 可以递归。如果您使用 CTE,您只需要父级 IS。查看 https://technet.microsoft.com/pl-pl/library/ms186243(v=sql.105).aspx
由于您没有为 ID/Parent 使用字符串,您可以利用 hierarchyid
数据类型。
R1,R2 和 HierPath 在最后 select 是可选的。 R1 和 R2 表示所有权范围。这有助于聚合和 selection 而无需递归。
例子
;with cteP as (
Select ID
,ParentId
,HierID = convert(hierarchyid,concat('/',ID,'/'))
From Items
Where ParentId=0
Union All
Select ID = r.ID
,ParentId = r.ParentId
,HierID = convert(hierarchyid,concat(p.HierID.ToString(),r.ID,'/'))
From Items r
Join cteP p on r.ParentId = p.ID)
Select R1 = Row_Number() over (Order By HierID)
,R2 = Row_Number() over (Order By HierID) + -1 + (Select count(*) From cteP where HierID.ToString() like A.HierID.ToString()+'%')
,Lvl = HierID.GetLevel()
,ID
,ParentId
,HierID
,HierPath = HierID.GetDescendant ( null , null ).ToString()
From cteP A
Order By A.HierID
Returns
根据要求。以下可以在几秒钟内生成 200K 层
I should add... Where you see
Row_Number() over (Order By ID)
I used ID, but this can be any other field to determine the desired presentation sequence.
例子
Select *,Lvl=1,Seq=cast(1000000+Row_Number() over (Order By ID) as varchar(900)) Into #TempBld from Items Where ParentID = 0
Declare @Cnt int=1
While @Cnt<=30
Begin
Insert Into #TempBld
Select A.*,Lvl=B.Lvl+1,Seq=B.Seq+' '+ cast(1000000+Row_Number() over (Order By A.ID) as varchar(25))
From Items A
Join #TempBld B on (B.Lvl=@Cnt and A.ParentID=B.ID)
Set @Cnt=@Cnt+1
End
Select ID,R1=cast(Row_Number() over (Order by Seq) as int),Seq Into #TempR1 From #TempBld
Create Clustered Index idx on #TempR1 (Seq)
Select A.ID,R2 = Max(B.R1) Into #TempR2 From #TempBld A Join #TempR1 B on B.Seq Like A.Seq+'%' Group By A.ID
Select B.R1
,C.R2
,A.Lvl
,A.ID
,A.ParentID
From #TempBld A
Join #TempR1 B on (A.ID=B.ID)
Join #TempR2 C on (A.ID=C.ID)
Order By 1
Returns