7

ループする CTE 内で GROUP BY を使用する回避策はありますか、または回避策はありますか?

CTE テーブルの結果セットをグループ化し、同じ CTE を持つ別のループで使用する必要がありますが、次のエラーが発生します。

GROUP BY、HAVING、または集約関数は、再帰共通テーブル式 'cte' の再帰部分では許可されていません。

クエリは次のとおりです。

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 (サンプルデータ付き)


編集...これは論理的な問題です

一連のエンド ユーザー アイテム (父 = NULL) と、他の多くのアイテム (フィールドの父と入力されたフィールド番号) によって作成された他のサブアイテムがあります。エンドユーザー アイテムの Dailyconsumption を取得し (CTE を "WHERE Father IS NULL" で開始)、サブアイテムの 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

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

この有効なクエリを使用して、すべてのアイテム (エンドユーザーとサブアイテム) のすべての Dailyconsumption を入力します。父と息子の関係は 1 レベル以上の深さになる可能性があることに注意してください。

ここで、カットオフを計算する必要があります (私の在庫で十分な日数)。最終用途では非常に簡単で、最初の CTE: stock/dailyconsumptionで既に計算されています。サブアイテムの場合は、もう少し複雑です: 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

代わりに変数テーブルを使用することをお勧めします。テーブルを宣言してから、それらのレコードをテーブルに挿入します。2番目のinsert intoコマンドでループする方法を見つける必要があります。私はあなたが始めるためにこれを手に入れました:

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 に答える