4

私の同僚は、私が彼を助けようとしている問題を抱えています。

彼は、次のデータ (サンプル データ) を含む SQL ビューを持っています。

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

彼は、[値] 列の累計を保持する列をビューに追加したいと考えています。

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

したがって、出力データは次のようにする必要があります:-

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 列がなく、カテゴリが変更されたときに現在の合計をリセットするようにどのように指示するのでしょうか??

4

2 に答える 2

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() はここに記載されているとおりに機能します が、基本的には、パーティショニング (基本的にはグループ化と同じですが、メイン クエリでグループ化する必要はありません) と組み込みのクラスによる順序に応じて自動インクリメントします。

この例では、クラスごとに分割することで、新しい各カテゴリ名の最小値が 1 に設定されるようにします。特定のカテゴリに基づいていない現在の合計が必要な場合は、句のこの部分を削除します。

CTE の 2 番目の部分は、CTE の最初の部分からの結果を選択し、クラスが一致する部分に結合します。r2.row <= r1.row で結合することにより、2 番目の結合にすべての値 <= 現在の行が含まれることが保証されます。つまり、R1 の行 3 には R2 結合の行 1、2、3 が含まれます。

于 2012-04-30T08:58:15.830 に答える
3

ROW_NUMBER()と組み合わせて関数を使用できます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
于 2012-04-30T09:00:20.560 に答える