2

我有一個遞歸的CTE工作正常,但我需要一件事:添加[isLeaf]標誌給每個結果,這將告訴如果記錄有更多的孩子([Leafs]字段與兒童櫃檯會更好)。遞歸cte - 標記所有葉子

粘貼在下面的工作示例。它計算每個類別的級別並將名稱加入到類別路徑中,但是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 
+1

從Sql Server 2008開始,您可能會使用特殊數據類型[hierarchyId](http://technet.microsoft.com/en-us/library/bb677213%28v=sql.105%29.aspx)用於分層數據。 –

+0

@NikolaMarkovinović偉大的提示,謝謝!我不知道這種類型的存在,但現在我可以在我的項目中看到很多應用程序。 –

回答

2

最簡單的事情就是要在檢查IsLeaf最終選擇語句添加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(自下而上而不是從上到下)。