2012-04-30 10 views
4

私の同僚には私が彼を助けようとしている問題があります。列Aが変更されたときに表示されるSQL Serverクエリ合計がリセットされます

彼は次のようなデータ(サンプルデータ)を含むSQLビューを持っている: -

Category   Value 
Cat A    10 
Cat A    20 
Cat A    30 
Cat B    15 
Cat B    15 
Cat C    10 
Cat C    10 

彼はValue列の累計を保つビューに列を追加したいと考えています。

この列は、カテゴリが変更されたときに実行中の合計をリセットする必要があります。

ので、出力データは次のようにする必要があります -

Category   Value  Running 
Cat A    10   10 
Cat A    20   30 
Cat A    30   60 
Cat B    15   15 
Cat B    15   30 
Cat C    10   10 
Cat C    10   20 

我々はこのようにそれ自体にテーブルを結合して累計を得ることができる: -

select t1.id, t1.[count], SUM(t2.[count]) as sum 
from TableA t1 
inner join TableA t2 on t1.id >= t2.id 
group by t1.id, t1.[count] 
order by t1.id 

問題は致しておりませんID列があり、カテゴリーが変更されたときに実行中の合計がリセットされるように指示する方法はありますか?

+1

と組み合わせるROW_NUMBER()機能を使用することができますか?これは、最終的に(完全に)ウィンドウ関数をサポートしているため、SQL Server 2012では非常に簡単です。 –

+1

残念ながら、SQL Server 2005。 –

+0

実行中の合計の順序はどのように計算されますか?テーブルに日付フィールドはありますか? – Dibstar

答えて

4

これは、大きなテーブルでは特にうまく機能しませんが、その作業を行います!

select 'Cat A' as class,10 as value into #x 
UNION ALL SELECT 'Cat A',20 
UNION ALL SELECT 'Cat A',30 
UNION ALL SELECT 'Cat B',15 
UNION ALL SELECT 'Cat B',15 
UNION ALL SELECT 'Cat C',10 
UNION ALL SELECT 'Cat C',10 

;WITH running_total AS 
(
select * 
,ROW_number() OVER (PARTITION BY class order by value ASC) as row 
from #x 
) 
SELECT 
r1.class 
,MAX(r1.value) as value 
,SUM(r2.value) as running_total 
FROM running_total r1 
LEFT OUTER JOIN running_total r2 on r2.class = r1.class 
       AND r2.row <= r1.row 
GROUP BY 
r1.class 
,r1.row 

これは、共通テーブル式(CTE)とウィンドウ関数を使用して動作します。 CTEはサブクエリと同様に動作し、最初の部分(running_total)は値に基づいて各クラスに行ベースのIDを追加します。

Row_number()は文書番号hereとして動作しますが、基本的にはパーティション化の定義方法(基本的にはグループ単位と同じですが、メインクエリでグループ化する必要はありません)とクラスごとの組み込み順序に従って自動インクリメントします。

この例では、partitionign by classを使用すると、新しいカテゴリ名の最小値が1に設定されます。特定のカテゴリに基づいていない合計の合計が欲しい場合は、この部分を削除します。

CTEの2番目の部分は、CTEの最初の部分の結果を選択し、クラスが一致する場所に結合します。 r2.rowに参加することによって、< = r1.rowは、2番目の結合にすべての値が含まれていることを確認します。< =現在の行 - つまり、R1のRow 3にはR2 joinのRow 1,2,3が含まれます。

+0

あなたはこれがどのように機能しているのか、答えが以下のような注文を指定する方法があるかどうかを正確に教えてください。 – JsonStatham

+1

編集を参照してください - 注文を変更するという観点から、ROW_NUMBER()句のORDER BY ...部分を注文通りに変更することができます – Dibstar

+0

下部に注文が必要なので、 view – JsonStatham

3

あなたはどのSQL ServerのバージョンOUTER APPLY

DECLARE @T TABLE (Category VARCHAR(5), Value INT) 
INSERT INTO @T VALUES 
    ('Cat A', 10), 
    ('Cat A', 20), 
    ('Cat A', 30), 
    ('Cat B', 15), 
    ('Cat B', 15), 
    ('Cat C', 10), 
    ('Cat C', 10) 

;WITH T AS 
( SELECT Category, Value, ROW_NUMBER() OVER(PARTITION BY Category ORDER BY Value) [RowNumber] 
    FROM @T 
) 
SELECT T1.Category, 
     T1.Value, 
     RunningTotal 
FROM T T1 
     OUTER APPLY 
     ( SELECT SUM(Value) [RunningTotal] 
      FROM T T2 
      WHERE T2.Category = T1.Category 
      AND  T2.RowNumber <= T1.RowNumber 
     ) RunningTotal 
+1

両方の回答を試しましたが、これは6分以上で実行されています。答えは3秒で実行されます。どちらも正しく動作します。 – JsonStatham