7

是否有在循环 CTE 中使用 GROUP BY 的解决方法或有解决方法?

我需要对 CTE 表的结果集进行分组,并在具有相同 CTE 的另一个循环中使用它,但出现以下错误:

递归公用表表达式“cte”的递归部分中不允许使用 GROUP BY、HAVING 或聚合函数。

这是查询:

WITH cte
    AS
    (
        SELECT
          id,
          dailyconsumption,
          stock/dailyconsumption as cutoff
        FROM items
        WHERE father IS NULL


        UNION ALL

        SELECT
          i.id,
          SUM(father.dailyconsumption*i.num),
          MAX(stock)/SUM(father.dailyconsumption*i.num)
        FROM cte father
        JOIN items i ON father.id=i.father
        group by i.id
    )

SELECT id, MIN(cutoff)
FROM cte
GROUP BY id

SQL-Fiddle(带有示例数据)


编辑...这是逻辑问题

我有一组最终用户项目(father=NULL)和由许多其他项目(字段父亲和字段 num 填充)组成的其他子项目。我得到了最终用户项目的每日消耗量(我的 cte 以“WHERE 父亲为 NULL”开始),子项目的每日消耗量由 SUM(father.dailyconsumption *item.num)计算。

WITH cte AS(
    SELECT
      id,
      dailyconsumption,
      stock/dailyconsumption as cutoff
    FROM items
    WHERE father IS NULL


    UNION ALL

    SELECT
      i.id,
      father.dailyconsumption*i.num
      0
    FROM cte father
    JOIN items i ON father.id=i.father
)

SELECT id, SUM(dailyconsumption)
FROM cte
GROUP BY id

http://sqlfiddle.com/#!3/f4f2a/95

通过这个有效的查询,我将为所有项目(最终用户和子项目)填充所有日常消费。请注意,父子关系可以超过 1 级。

现在我需要计算截止值(我的库存是多少天)。对于最终用途,它非常容易并且已经在第一个 CTE 中计算出来:库存/每日消费。对于子项目,它有点复杂: subitem.stock/subitem.dailyconsumption + MIN(father.cutoff) 其中 MIN(father.cutoff) 是该子项目所有父亲的最小截止值。这是因为我需要另一个分组。

我可以需要另一个 CTE 来循环相同的父子关系吗?

谢谢你的关注,对不起我的英语。

4

2 回答 2

5
;WITH cte AS
 (
  SELECT id, father, 
         dailyconsumption,
         (stock / dailyconsumption) AS cutoff,
         0 AS [Level] 
  FROM items
  WHERE father IS NULL
  UNION ALL
  SELECT i.id, i.father, 
         c.dailyconsumption * i.num,
         i.stock / (c.dailyconsumption * i.num),
         [Level] + 1
  FROM cte c JOIN items i ON c.id = i.father
  )
  SELECT c.id, c.dailyconsumption, c.cutoff AS subItemsCutoff, 
         MIN(ct.cutoff) OVER(PARTITION BY ct.[Level]) AS fatherCutoff,
         (c.cutoff  + ISNULL(MIN(ct.cutoff) OVER(PARTITION BY ct.[Level]), 0)) AS Cutoff
  FROM cte c LEFT JOIN cte ct ON c.father = ct.id

SQLFiddle上的演示

于 2012-12-28T11:37:57.327 回答
0

我建议改用变量表。声明表,然后将这些记录插入其中。您需要找到一种在第二次插入命令时循环遍历它的方法。我得到这个让你开始:

DECLARE @staging TABLE
(
    id                  INT
    ,dailyconsumption   FLOAT
    ,cutoff             FLOAT
)

INSERT INTO @staging
    SELECT
      id,
      dailyconsumption,
      stock/dailyconsumption as cutoff
    FROM 
      items
    WHERE 
      father IS NULL

INSERT INTO @staging
  SELECT
      i.id,
      SUM(father.dailyconsumption*i.num),
      MAX(stock)/SUM(father.dailyconsumption*i.num)
    FROM 
      @staging father

        JOIN items i 
        ON father.id=i.father
    group by 
      i.id

SELECT 
  id
 ,MIN(cutoff)
FROM 
  @staging
GROUP BY 
  id
于 2012-12-19T17:56:22.773 回答