5

SQL Server で再帰的な合計を計算する必要があります。親 ID を渡して、その親 ID にリンクされているすべての子 (および子の子) の合計を返すことができるストアド プロシージャが必要です。

これが私がこれまでに持っているものです

IF object_id('tempdb..#Averages') IS NOT NULL
BEGIN
   DROP TABLE #Averages
END


CREATE TABLE #Averages
(
ID INT PRIMARY KEY CLUSTERED IDENTITY(1,1),
Name VARCHAR(255),
ParentID int,
Value INT
)

INSERT INTO #Averages(Name,ParentID,Value)VALUES('Fred',NULL,1)
INSERT INTO #Averages(Name,ParentID,Value)VALUES('Bets',NULL,1)

INSERT INTO #Averages(Name,ParentID,Value)(SELECT 'Wynand',ID,21 FROM #Averages WHERE      Name = 'Fred'  )

INSERT INTO #Averages(Name,ParentID,Value)(SELECT 'Dewald',ID,27 FROM #Averages WHERE     Name = 'Fred'  )
INSERT INTO #Averages(Name,ParentID,Value)(SELECT 'Katelynn',ID,1 FROM #Averages WHERE Name = 'Dewald'  )

INSERT INTO #Averages(Name,ParentID,Value)(SELECT 'Jacques',ID,28 FROM #Averages WHERE Name = 'Bets'  )
INSERT INTO #Averages(Name,ParentID,Value)(SELECT 'Luan',ID,4 FROM #Averages WHERE Name = 'Jacques'  )
INSERT INTO #Averages(Name,ParentID,Value)(SELECT 'Ruben',ID,2 FROM #Averages WHERE Name = 'Jacques'  )


;WITH Personal AS
(
SELECT N=1, ID,Name,ParentID,Value
FROM #Averages 
WHERE ParentID IS NULL
UNION ALL
SELECT N+1, Av.ID,Av.Name,Av.ParentID,Av.Value
FROM #Averages Av
INNER JOIN  Personal P ON P.ID = Av.ParentID
)

SELECT Name,
    SUM(Value) as Total
FROM Personal
WHERE N<=3
GROUP BY Name
4

2 に答える 2

3

上記のアプローチとは少し異なりますが、これはあなたが望むものを達成する1つの方法です:

SQLフィドル

Create Table #Ancestors (
    ID int
  ,  Name VARCHAR(255)  
  ,  ParentID int
  ,  AncestryCompleteTF tinyint
  ,  Ancestors varchar(max)
  ,  TotalValue int    
)

INSERT INTO #Ancestors
SELECT
    ID
  , Name
  , ParentID
  , CASE ISNULL(ParentID, 0)
     WHEN 0 THEN 1
     ELSE 0
    END
  , CONVERT(VARCHAR, ISNULL(ParentID, ''))
  , Value
FROM
   Averages

WHILE EXISTS (SELECT * FROM #Ancestors WHERE AncestryCompleteTF = 0) 
BEGIN
  UPDATE C SET 
    C.Ancestors = P.Ancestors + ',' + CONVERT(VARCHAR, P.ID),
    C.AncestryCompleteTF = 1,
    C.TotalValue = P.TotalValue + C.TotalValue
  FROM #Ancestors C 
    INNER JOIN #Ancestors P ON (C.ParentID = P.ID) 
    AND P.AncestryCompleteTF = 1
END

SELECT 
  Name
, TotalValue 
FROM 
  #Ancestors

基本的に、一時テーブルを作成し、while ループを使用して、親が既に計算されている行の合計を更新し続けます (これは、現在の行の合計を親行の合計に追加する場合にすぎないため)。計算されています。ParentID が null の行は最初から完了済みに設定されているため、最初にその直系の子孫が計算され、次にそれらの行の子孫などが計算されます。

于 2012-07-10T08:33:52.397 に答える
2

少し遊んだ後、私はそれを手に入れたと思います。CTE のルートに設定した最上位 ID を追加しました。そして、すべての再帰の最上位 ID を追加するだけです。

最後に、合計するだけで、基本的に TopLevelId を使用して最上位テーブルに結合します。

IF object_id('tempdb..#Averages') IS NOT NULL
BEGIN
   DROP TABLE #Averages
END

CREATE TABLE #Averages
(
    ID INT PRIMARY KEY CLUSTERED IDENTITY(1,1),
    Name VARCHAR(255),
    ParentID int,
    Value INT
)

 INSERT INTO #Averages(Name,ParentID,Value)VALUES('Fred',NULL,1)
 INSERT INTO #Averages(Name,ParentID,Value)VALUES('Bets',NULL,1)

 INSERT INTO #Averages(Name,ParentID,Value)(SELECT 'Wynand',ID,21 FROM #Averages WHERE Name = 'Fred'  )

 INSERT INTO #Averages(Name,ParentID,Value)(SELECT 'Dewald',ID,27 FROM #Averages WHERE Name = 'Fred'  )
 INSERT INTO #Averages(Name,ParentID,Value)(SELECT 'Katelynn',ID,1 FROM #Averages WHERE Name = 'Dewald'  )

 INSERT INTO #Averages(Name,ParentID,Value)(SELECT 'Jacques',ID,28 FROM #Averages WHERE Name = 'Bets'  )
 INSERT INTO #Averages(Name,ParentID,Value)(SELECT 'Luan',ID,4 FROM #Averages WHERE Name = 'Jacques'  )
 INSERT INTO #Averages(Name,ParentID,Value)(SELECT 'Ruben',ID,2 FROM #Averages WHERE Name = 'Jacques'  )


;WITH Personal AS
(
    SELECT N=1, 
        ID,
        Name,
        ParentID,
        Value,
        TopLevelID =ID
    FROM #Averages 
    WHERE ParentID IS NULL

    UNION ALL

    SELECT N+1, 
        Av.ID,
        Av.Name,
        Av.ParentID,
        Av.Value,
        TopLevelID =P.TopLevelID
    FROM #Averages Av
    INNER JOIN  Personal P ON P.ID = Av.ParentID
)

SELECT SUM(P.Value) AS Total,
        A.Name
FROM Personal P
INNER JOIN #Averages A on A.ID = P.TopLevelID
GROUP BY A.Name
于 2012-07-10T08:53:35.650 に答える