如何使用 T-SQL 组合多个不同长度的父子关系?
How do I combine multiple parent-child relationships with different lengths using T-SQL?
总结
在 Azure 数据库中(使用 SQL Server Management Studio 17,所以 T-SQL)我试图连接多个不同长度的父子关系。
基础Table
我的table是这样的形式:
ID parent
1 2
2 NULL
3 2
4 3
5 NULL
随意使用此代码生成并填写它:
DECLARE @t TABLE (
ID int,
parent int
)
INSERT @t VALUES
( 1, 2 ),
( 2, NULL ),
( 3, 2 ),
( 4, 3 ),
( 5, NULL )
问题
如何接收 table 的路径串联,如下所示 table?
ID path parentcount
1 2->1 1
2 2 0
3 2->3 1
4 2->3->4 2
5 5 0
详情
真正的 table 有更多的行,最长的路径应该包含 ~15 个 ID。因此,理想的做法是找到一种在父计数定义方面是动态的解决方案。
另外:我不一定需要 'parentcount' 列,所以请在答案中跳过它。
select @@version:
Microsoft SQL Azure (RTM) - 12.0.2000.8
您可以为此使用递归 CTE:
with cte as (
select id, parent, convert(varchar(max), concat(id, '')) as path, 0 as parentcount
from @t t
union all
select cte.id, t.parent, convert(varchar(max), concat(t.id, '->', path)), parentcount + 1
from cte join
@t t
on cte.parent = t.id
)
select top (1) with ties *
from cte
order by row_number() over (partition by id order by parentcount desc);
很明显,Gordon 用递归 CTE 解决了这个问题,但这是使用 HierarchyID
数据类型的另一种选择。
例子
Declare @YourTable Table ([ID] int,[parent] int)
Insert Into @YourTable Values
(1,2)
,(2,NULL)
,(3,2)
,(4,3)
,(5,NULL)
;with cteP as (
Select ID
,Parent
,HierID = convert(hierarchyid,concat('/',ID,'/'))
From @YourTable
Where Parent is Null
Union All
Select ID = r.ID
,Parent = r.Parent
,HierID = convert(hierarchyid,concat(p.HierID.ToString(),r.ID,'/'))
From @YourTable r
Join cteP p on r.Parent = p.ID
)
Select ID
,Parent
,[Path] = HierID.GetDescendant ( null , null ).ToString()
,ParentCount = HierID.GetLevel() - 1
From cteP A
Order By A.HierID
Returns
总结
在 Azure 数据库中(使用 SQL Server Management Studio 17,所以 T-SQL)我试图连接多个不同长度的父子关系。
基础Table
我的table是这样的形式:
ID parent
1 2
2 NULL
3 2
4 3
5 NULL
随意使用此代码生成并填写它:
DECLARE @t TABLE (
ID int,
parent int
)
INSERT @t VALUES
( 1, 2 ),
( 2, NULL ),
( 3, 2 ),
( 4, 3 ),
( 5, NULL )
问题
如何接收 table 的路径串联,如下所示 table?
ID path parentcount
1 2->1 1
2 2 0
3 2->3 1
4 2->3->4 2
5 5 0
详情
真正的 table 有更多的行,最长的路径应该包含 ~15 个 ID。因此,理想的做法是找到一种在父计数定义方面是动态的解决方案。 另外:我不一定需要 'parentcount' 列,所以请在答案中跳过它。
select @@version:
Microsoft SQL Azure (RTM) - 12.0.2000.8
您可以为此使用递归 CTE:
with cte as (
select id, parent, convert(varchar(max), concat(id, '')) as path, 0 as parentcount
from @t t
union all
select cte.id, t.parent, convert(varchar(max), concat(t.id, '->', path)), parentcount + 1
from cte join
@t t
on cte.parent = t.id
)
select top (1) with ties *
from cte
order by row_number() over (partition by id order by parentcount desc);
很明显,Gordon 用递归 CTE 解决了这个问题,但这是使用 HierarchyID
数据类型的另一种选择。
例子
Declare @YourTable Table ([ID] int,[parent] int)
Insert Into @YourTable Values
(1,2)
,(2,NULL)
,(3,2)
,(4,3)
,(5,NULL)
;with cteP as (
Select ID
,Parent
,HierID = convert(hierarchyid,concat('/',ID,'/'))
From @YourTable
Where Parent is Null
Union All
Select ID = r.ID
,Parent = r.Parent
,HierID = convert(hierarchyid,concat(p.HierID.ToString(),r.ID,'/'))
From @YourTable r
Join cteP p on r.Parent = p.ID
)
Select ID
,Parent
,[Path] = HierID.GetDescendant ( null , null ).ToString()
,ParentCount = HierID.GetLevel() - 1
From cteP A
Order By A.HierID
Returns