我有一个递归的CTE工作正常,但我还需要一个东西:为每个结果添加[isLeaf]标志,这将告诉记录是否有更多的子项(带有子计数器的[Leafs]字段会更好)。
下面粘贴的工作示例。它计算每个类别的级别并将名称连接到类别路径,但是sql server不允许在CTE的递归部分中使用LEFT JOIN,TOP,SELECT DISTINCT,聚合和子查询,这是我做的事情的明显方法需要。
DROP TABLE cats
GO
create table cats(
catid int primary key clustered,
parent int, --parent's catid. 0 for top-level entries
name varchar(255)
)
GO
insert into cats (catid, parent, name)
select 1 as catid, 0 as parent, 'computers' as name union all
select 2, 1, 'laptops' union all
select 4, 2, 'ibm' union all
select 5, 2, 'others' union all
select 3, 1, 'desktops' union all
select 6, 3, 'amd' union all
select 7, 3, 'others' union all
select 8, 0 , 'cars' union all
select 9, 8, 'others' union all
select 10, 8, 'pickups' union all
select 11, 10, 'others' union all
select 12, 10, 'ford' union all
select 14, 12, 'ranger' union all
select 15, 12, 'others'
GO
;with cteCat as (
select
CatId, Parent,
[cteLevel] = 1,
[ctePath] = cast(Name as varchar(4000))
--,[cteIsLeaf] = 0
from cats
where 1=1
and Parent=0
union all
select
c.CatId, c.Parent,
[cteLevel] = cc.cteLevel+1,
[ctePath] = cast(cc.ctePath + ' | ' + c.Name as varchar(4000))
--,[cteIsLeaf] = 0 --???--
from cats c
join cteCat cc
on c.Parent = cc.CatId
where 1=1
and c.Parent<>0
)
select
*
from cteCat
order by
catid
答案 0 :(得分:2)
实现最简单的方法就是在检查IsLeaf
的最终select语句中添加corraleted子查询。这是一个简单的检查,看看特定CatID
是否是某人的父母。不需要递归。
SELECT
* , CASE WHEN EXISTS (SELECT * FROM cats c2 WHERE c2.parent = c1.CatID) THEN 0 ELSE 1 END AS IsLeaf
FROM cteCat c1
ORDER BY
catid
编辑:
如果您需要[Leafs]
作为即将到来的孩子的计数,那么获取它们也很简单:
SELECT
*
, CASE WHEN EXISTS (SELECT * FROM cats c2 WHERE c2.parent = c1.CatID) THEN 0 ELSE 1 END AS IsLeaf
, (SELECT COUNT(*) FROM cats c2 WHERE c2.parent = c1.CatID) AS Leafs
FROM cteCat c1
ORDER BY
c1.catid
<强> SQLFiddle DEMO 强>
但是,如果您需要[Leafs]
作为儿童和所有儿童的孩子的总计数器,则需要重写您的CTE(自下而上而不是从上到下)。