3

我有一个运行良好的递归 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
4

1 回答 1

3

最容易实现的事情就是在检查IsLeaf. 这是一个简单的检查来查看特定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 演示

但是,如果您需要[Leafs]作为孩子和所有孩子的孩子的总计数器,则需要重写您的 CTE(自下而上而不是自上而下)。

于 2013-08-26T08:08:41.190 回答