web-dev-qa-db-ja.com

あるカテゴリーに基づいた前のn列の合計

各カテゴリの過去x週間の値の合計を計算する必要がある次の入力があります。

input

Xが3の場合、出力は次のようになります。

enter image description here

最後の値は49であることに注意してください。これは、x = 3から現在の週に最後の2週間の値のみを追加したためです。

SQLをストアドプロシージャとして記述したいと考えており、これを行う適切な方法について支援が必要です。

@sp_BlitzErikの助けを借りて、私は [〜#〜] lag [〜#〜] を使用しようとしましたが、必要な場所を完全に取得できませんでした。これが私のクエリです:

SELECT category
    ,year
    ,week
    ,value
    ,(
        LAG(value, 1, 0) OVER (
            ORDER BY category
                ,year
                ,week
            ) + LAG(value, 2, 0) OVER (
            ORDER BY category
                ,year
                ,week
            ) + value
        ) AS cumulative_value
FROM valuedata

そして、出力はまだ完全に正しくありません:

enter image description here

4
user3885927

SQL Server 2014および2016 1 WINDOW関数(つまり、 OVER 句)を使用して、必要なことを実行できます。

SELECT
     category, year, week, value, 
     sum(value) OVER (PARTITION BY category 
                          ORDER BY year, week 
                              ROWS 2 PRECEDING) AS retention_value_3_weeks
FROM
     t 
ORDER BY
    category, year, week ;

そして、これはあなたが得る結果です:

カテゴリ|年|週|値| tention_value_3_weeks 
:---- ---:| ---:| ----:| ----------------------:
 a | 2016 | 1 | 5 | 5 
 a | 2016 | 2 | 7 | 12 
 a | 2016 | 3 | 8 | 20 
 b | 2016 | 3 | 6 | 6 
 b | 2016 | 4 | 15 | 21 
 b | 2016 | 5 | 25 | 46 
 c | 2016 | 3 | 25 | 25 
 c | 2016 | 4 | 2 | 27 
 c | 2016 | 5 | 21 | 48 
 c | 2016 | 6 | 26 | 49 

あなたの例のx = 3は(現在の行2 preceding ones)。

何らかの理由でOVER句を使用できない場合でも、いくつかの(かなり複雑な)サブクエリを使用して同じ結果を計算できます。

SELECT
    category, year, week, value,
    (SELECT 
        sum(value)
     FROM
        (SELECT TOP 3                    /* total number of rows to consider */
             value
        FROM 
           t t2
        WHERE
               t2.category = t.category  /* partition by category */
           AND t2.week <= t.week         /* current and preceding rows */
        ORDER BY
           year DESC, week DESC          /* order by criteria */
        ) AS q
     ) AS retention_value_3_weeks
FROM
    t 
ORDER BY
    category, year, week ;

dbfiddle ---(hereですべて確認してください

@xの代わりに3を使用する場合は、次のようにすることができます。

DECLARE @x AS INTEGER = 3;

SELECT
    category, year, week, value,
    (SELECT 
        sum(value)
     FROM
        (SELECT TOP (@x)                  /* total number of rows to consider */
             value
        FROM 
           t t2
        WHERE
               t2.category = t.category  /* partition by category */
           AND t2.week <= t.week         /* current and preceding rows */
        ORDER BY
           year DESC, week DESC          /* order by criteria */
        ) AS q
     ) AS retention_value_3_weeks
FROM
    t 
ORDER BY
    category, year, week ;;

dbfiddle ここ


1) SQL Server 2012がないため、SQL Server 2012でテストできません。 MS SQL Serverのドキュメントには、バージョン2008以降で利用可能である必要があると記載されています。

4
joanolo

これは、@ sp_BlitzErikからの [〜#〜] lag [〜#〜] ヒントで得られたものであり、結果はまさに私が欲しかったものです。

SELECT category
    ,year
    ,week
    ,value
    ,(
        LAG(value, 1, 0) OVER (
            PARTITION BY category ORDER BY year
                ,week
            ) + LAG(value, 2, 0) OVER (
            PARTITION BY category ORDER BY year
                ,week
            ) + value
        ) AS cumulative_value
FROM valuedata

しかし、これは十分なジェネリックではありません。より良い答えがある場合は投稿してください。

1
user3885927
SELECT
    category, year, week, value,
    (SELECT 
        sum(t2.value)
     FROM
           t t1 INNER JOIN t t2
        WHERE
               t1.category = t2.category  /* partition by category */
           AND t1.week >= t.week + 2        /* current and preceding rows */
        GROUP BY t1.category, t1.year, t1.week      /* group by criteria */
        ) AS q
     ) AS retention_value_3_weeks
FROM
    t 
ORDER BY
    category, year, week ;
0
Aakash