sql视图错误中的递归计算递归部分中不允许使用GROUP BY,HAVING或聚合函数

时间:2015-04-10 20:09:58

标签: sql-server recursion

我有一个非常简单的SQL Server表,我想找到每个食谱的成本。每个食谱都有一份食材清单。食谱也可能有子食谱。

最简单的RecipeId-1鸡肉三明治示例,其成分低于:

  1. IngredientId-1面包(成分) - 成本$ 1
  2. IngredientId-2炸鸡(一种成分) - 成本$ 5
  3. RecipeId-2蒜酱(子食谱) - 费用$ 2
  4. 由于蒜酱RecipeId-2也是配方(用作上面的子配方),它有以下成分:

    1. IngredientId-3 Raw Garlic - 成本$ 1.5
    2. IngredientId-4 Water - 成本$ 0.5
    3. 最后我的表结构:

      enter image description here

      现在我想要一个能让我获得鸡肉三明治费用的视图 选择*来自RecursiveRecipeView其中RecipeId = 1,结果将是:$ 8(1 + 5 + 1.5 + .5)。

      我试过下面的查询,但是我收到错误“在递归公用表表达式'Tree'的递归部分中不允许使用GROUP BY,HAVING或聚合函数”

      WITH Tree (RecipeId, Depth, SubRecipeId, Cost) AS (
      SELECT RecipeId, 0 AS Depth, RecipeId AS SubRecipeId, SUM(Cost) AS [Cost] FROM RecipeIngredients
      GROUP BY RecipeId
      UNION ALL
      SELECT RI.RecipeId, Parent.Depth + 1 AS Depth,
      CONVERT(varchar(255), Parent.SubRecipeId) AS SubRecipeId, Parent.Cost + cast(sum(RI.cost) as float) AS [Cost] 
      FROM RecipeIngredients RI
      INNER JOIN Tree as Parent ON Parent.RecipeId = RI.SubRecipeId )SELECT distinct RecipeId, Depth, SubrecipeId, Cost FROM Tree
      

      请注意,有些食谱甚至可以达到10级。有人可以帮我吗?

1 个答案:

答案 0 :(得分:2)

首先,您的CTE出现了一些问题。它将无限地递归,这是不好的。我在您的TREEPARENT个对象之间翻转了您的联接。

其次,正如已经指出的那样,您需要将聚合从CTE中拉出来。只需让您的CTE选择您的详细信息,然后在最终查询中总结。这里有一个问题是你需要在CTE的顶层指定一个特定的RecipeID,这样你才真正拥有“顶级”水平。

SQLFiddle(我添加了第三级,只是为了测试它)。

WITH Tree (RecipeId, Depth, SubRecipeId, Cost) AS (
SELECT RecipeId, 
  0 AS Depth, 
  SubRecipeId, 
  Cost 
FROM RecipeIngredients 
  where recipeid = 1
UNION ALL
SELECT 
  parent.RecipeId, 
  Parent.Depth + 1 AS Depth,
  ri.SubRecipeId AS SubRecipeId, 
  RI.cost as cost
FROM RecipeIngredients  RI
INNER JOIN Tree as Parent 
  ON Parent.subrecipeid = RI.recipeid 
)

SELECT * FROM Tree
--select sum(cost) from Tree