TSQL GROUP BY在递归CTE中

Tob*_*bia 7 t-sql sql-server common-table-expression

是否有解决方法在循环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
Run Code Online (Sandbox Code Playgroud)

SQL-Fiddle(带有示例数据)


编辑......这是合乎逻辑的问题

我有一组最终用户项(父= NULL)和其他一些子项(由字段父和字段num填充).我只为最终用户项目获得了每日消费(我用"WHERE father IS NULL"开始我的cte),并且子项的dailyconsumption由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
Run Code Online (Sandbox Code Playgroud)

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

使用此有效查询,我将为所有项目(最终用户和子项目)填充所有dailyconsumption.请注意,父子关系可以超过1级.

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

我是否需要另一个CTE来循环同一个父子关系?

感谢您的关注,对不起我的英语.

Ale*_*nko 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
Run Code Online (Sandbox Code Playgroud)

关于SQLFiddle的演示


Nei*_*eil 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
Run Code Online (Sandbox Code Playgroud)