SQL Server中的表具有多代的父引用的子映射。
我必须达到结果:
Level No || Child Count
所以,我有以下查询:
SELECT
'L1' LEVEL, COUNT(ChildRef) CHILD
FROM
[dbo].[TOMatriX]
WHERE
ParentRef = 1
UNION ALL
SELECT
'L2' LEVEL, COUNT(ChildRef) CHILD
FROM
[dbo].[TOMatriX]
WHERE
ParentRef IN (SELECT ChildRef FROM [dbo].[TOMatriX] WHERE ParentRef = 1)
UNION ALL
SELECT
'L3' LEVEL, COUNT(ChildRef) CHILD
FROM
[dbo].[TOMatriX]
WHERE
ParentRef IN (SELECT ChildRef FROM [dbo].[TOMatriX]
WHERE ParentRef IN (SELECT ChildRef FROM [dbo].[TOMatriX]
WHERE ParentRef = 1)
)
UNION ALL
SELECT
'L4' LEVEL, COUNT(ChildRef) CHILD
FROM
[dbo].[TOMatriX]
WHERE
ParentRef IN (SELECT ChildRef FROM [dbo].[TOMatriX]
WHERE ParentRef IN (SELECT ChildRef FROM [dbo].[TOMatriX]
WHERE ParentRef IN (SELECT ChildRef
FROM [dbo].[TOMatriX]
WHERE ParentRef = 1)
)
)
如何使此查询动态化?没有硬编码,因为水平也可以超过4。
如何使用Common Table Expressions或其中的任何递归?
答案 0 :(得分:1)
说我们有下表:
create table #t1 (childref int, parentref int)
go
insert #t1 values
(1, null),
(2, 1),
(3, 1),
(4, 2),
(5, 2),
(6, 4),
(7, 4),
(8, 5),
(9, 6)
go
我们可以使用递归CTE来遍历层次结构并计算每个级别的项目:
;with x as (
select childref, 0 as lvl
from #t1
where parentref is null
union all
select #t1.childref, x.lvl+1
from #t1
inner join x on #t1.parentref = x.childref
)
select lvl, count(*)
from x
group by lvl
这是你想要的结果。让我们看看它是如何运作的。
递归CTE有两个部分(简单来说):锚点和resursive部分。主播:
select childref, 0 as lvl
from #t1
where parentref is null
执行一次,结果暂时存储。然后执行递归成员
select #t1.childref, x.lvl+1
from #t1
inner join x on #t1.parentref = x.childref
查看内部联接?这里的'x'实际上是对锚成员的结果的引用。我们加入的列必须包含在选择列表中。
存储此步骤的结果,并且是下一步骤的基础。
再次执行递归成员,这次加入上一步的结果。依此类推,只要递归步骤返回任何行,或者未达到maxrecursion。
UNION ALL
这里只是将这两者连接在一起的语法。
lvl
被添加到选择中以表示当前级别,并在每一步增加。
如果您在CTE之后只是select * from x
,则可以看到原始输出。我们所做的是用lvl对它进行分组并计算行数。