2013-04-25 97 views
2

我有一组数据,如下列:SQL服务器 - 面包屑型效应

ID, Description, ParentID 
1, Savoury, -1 
2, Cheese, 1 
3, Pastry, 1 
4, Quiche, 1 
5, Sweet, -1 
6, Chocolate, 5 
... 

什么我希望做的是写这将产生类似于面包屑一组结果的存储过程在网络浏览器中链接。类似以下内容将是理想的...

ID, BreadCrumb 
1, Savoury 
2, Savoury >> Cheese 
3, Savoury >> Pastry 
4, Savoury >> Quiche 
5, Sweet 
6, Sweet >> Chocolate 
... 

项目如奶酪或糕点不会被列为自己的项目(如甜)。到目前为止,我有以下的代码工作,但它列出的一切,不管它是否有PARENTID

With BreadCrumb AS 
(
SELECT CAST(a.Description AS VARCHAR(100)) AS Path, a.ID, a.ParentID 
FROM FoodStuff a 

UNION ALL 

SELECT CAST(BreadCrumb.Path + ' >> ' + b.Description AS VARCHAR(100)) AS Path, b.ID, b.ParentID 
FROM FoodStuff b 
INNER JOIN BreadCrumb ON BreadCrumb.ID = b.ParentID 

) 

SELECT * FROM BreadCrumb 
ORDER BY Path 

我会在正确的方向轻推感激。

由于提前, 千电子伏

回答

3

你需要为了在递归CTE的锚定器部分的条件将其限制在根项目:

With BreadCrumb AS 
(
SELECT CAST(a.Description AS VARCHAR(100)) AS Path, a.ID, a.ParentID 
FROM FoodStuff a 
WHERE a.ParentID = -1 -- select roots only 

UNION ALL 

SELECT CAST(BreadCrumb.Path + ' >> ' + b.Description AS VARCHAR(100)) AS Path, b.ID, b.ParentID 
FROM FoodStuff b 
INNER JOIN BreadCrumb ON BreadCrumb.ID = b.ParentID 
) 

你并不需要一个类似的条件在CTE的递归一半中,由于内部连接应该照顾它,因为可能是您没有ID = -1的任何记录。

作为一种最佳实践,我建议使用NULL而不是-1作为允许不具有值的外键,例如ParentID。

SQL Fiddle,感谢@Conrad Frix。

+0

这只是完美的。谢谢你的帮助! – weblar83 2013-04-25 20:03:34

+1

这里是[你的回答]的小提琴(http://sqlfiddle.com/#!6/4c84c/2) – 2013-04-25 20:03:57