SQL Server - 面包屑类型效果

时间:2013-04-25 19:51:05

标签: sql-server stored-procedures

我有一组数据如下:

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

我要做的是编写一个存储过程,它将生成一组类似于Web浏览器中的痕迹链接的结果。像下面这样的东西是理想的......

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

奶酪或糕点等物品不会单独列为物品(如Sweet)。到目前为止,我有以下代码可以工作,但它列出了所有内容,无论它是否有一个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

我很感激能够朝着正确的方向努力。

提前致谢, 千电子伏

1 个答案:

答案 0 :(得分: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提供。