CTE获取父母的所有孩子(后代)

Sam*_*Ccp 12 sql-server common-table-expression

我有这个让我头疼的问题......

说,我有一个包含数千行的表,表的结构包含父 - >子关系.

这种关系可以达到6个级别.这是表结构的示例:

ProductId | ParentId | Levels
1174           0        1174
311           1174      311, 1174
1186          311       1186, 311, 1174
448           1186      448, 1186, 311, 1174
3365          448       3365, 448, 1186, 311, 1174
Run Code Online (Sandbox Code Playgroud)

我们有一个循环遍历整个表以获取关系并保存"级别"列的进程,这个过程非常慢(因为循环)并且我尝试了一些cte来获得关系,但是很难实现.

到目前为止,我已经尝试过这个cte,但它没有做我希望的事情,而且,它似乎在复制行...

;With Parents(ProductId, ParentId, Levels)
As(
  Select ProductId, ParentId, Levels
  From Products
  Where ParentId = 0 
  Union All
  Select p.ProductId, p.ParentId, p.Levels
  From Products p
  Join Parents cte On cte.ProductId = p.ParentId
)
Select *
From Parents
Run Code Online (Sandbox Code Playgroud)

正如我之前提到的,我们有一个循环表的过程,它完成它的工作,但它可能需要长达30分钟,我的问题是有更好的方法来做到这一点?我知道CTE允许我这样做,但我很糟糕,同样,应该在桌面上计算和更新关卡列,是否可能?

这是一个Sqlfiddle以防有人可以提供帮助,谢谢!

Joh*_*tos 39

这应该这样做:

WITH MyTest as
(
  SELECT P.ProductID, P.ParentID, CAST(P.ProductID AS VarChar(Max)) as Level
  FROM Products P
  WHERE P.ParentID = 0

  UNION ALL

  SELECT P1.ProductID, P1.ParentID, CAST(P1.ProductID AS VarChar(Max)) + ', ' + M.Level
  FROM Products P1  
  INNER JOIN MyTest M
  ON M.ProductID = P1.ParentID
 )
SELECT * From MyTest
Run Code Online (Sandbox Code Playgroud)

这是更新的SQL小提琴.

另外,请查看此链接以获取有关CTE的帮助......他们绝对不错:

希望这可以解决问题!

  • 你将`Levels` 插入到你的 CTE 中,然后只是简单地查询出来......它扼杀了你想要完成的事情的想法。如果您查看我的 SQLFiddle,原始表甚至没有“Levels”列-我们根据需要根据产品/父列创建它... (2认同)
  • @NullHead不,`with`只需要成为语句中的第一个关键字.如果你正确地用半冒号终止你以前的陈述,你不需要在你的`with`前加一个. (2认同)