Reputation: 13161
I have a recursive CTE that's working fine, but I need one more thing: add [isLeaf] flag to each result, which will tell if the record has any more children ([Leafs] field with children counter would be even better).
Working example pasted below. It counts the level of every category and joins names into category path, but sql server doesn't allow LEFT JOIN, TOP, SELECT DISTINCT, aggregates and subqueries to be used in recursive part of CTE, which are the obvious methods of doing what I need.
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
Upvotes: 4
Views: 1647
Reputation: 18559
Easiest thing to implement is just to add corraleted subquery in the final select statement that checks for IsLeaf
. It's a simple check to see if particular CatID
is someone's parent or not. Does not require recursion.
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
EDIT:
If you need [Leafs]
as count of just the imminent children it's also simple to get them:
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
But, If you need [Leafs]
as total counter of children and all of chieldren's children it would require rewriting your CTE (to go bottom-up instead of top-to-bottom).
Upvotes: 4