0

私は現在、次のようなデータを持っています(ただし、より大きくなります!)

/*--:::::::::::
DROP TABLE #target
DROP TABLE #Fact
*/--:::::::::::
CREATE TABLE #target 
    (
    PlayerKey INT,
    Name            VARCHAR(8),
    LiveKey     INT
    );
INSERT INTO #target 
    values
    (1,'michael',20130103),
    (2,'jackson',20130107);

CREATE TABLE #Fact 
    (
    DateKey     INT,
    PlayerKey INT,
    Amount      INT
    );
INSERT INTO #Fact 
    values
    (20130101,1,10),
    (20130102,1,90),
    (20130103,1,18),
    (20130103,2,79),
    (20130103,3,99),
    (20130104,2,15),
    (20130105,1,12),
    (20130105,2,15),
    (20130106,1,60),
    (20130107,1,96),
    (20130107,2,88),
    (20130107,4,28),
    (20130108,1,13),
    (20130108,2,15),
    (20130109,1,33),
    (20130109,2,67),
    (20130110,1,19),
    (20130110,2,17)
    ;

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

DECLARE @NumDays INT = 3;

WITH    basic_cte AS
        (
        SELECT  rn = ROW_NUMBER() OVER(PARTITION BY d.Name ORDER BY f.DateKey),
                f.DateKey,
                d.Name,
                f.Amount
        FROM    #Fact f
                INNER JOIN #target d ON
                  f.PlayerKey = d.PlayerKey AND
                  f.DateKey >= d.LiveKey AND
                  f.DateKey < CONVERT(CHAR(8),CONVERT(DATETIME,CONVERT(DATETIME,CONVERT(CHAR(8),d.LiveKey,112))+@NumDays),112)
        )
SELECT  x.*,
        "RollingAmount" = SUM(Amount) OVER(PARTITION BY Name ORDER BY DateKey)
FROM    basic_cte x;

これにより、以下が得られます。

ここに画像の説明を入力

DimDate利用可能な生産ビューがあると仮定すると、量が 0michaelの行があることを確認するにはどうすればよいですか?20130104

また、同じスクリプトで、PlayerKeys 3 と 4 を含むすべてのプレーヤーに数値を与える新しい列 "AmountAll" と "AmountAllRolling" を追加することは可能ですか? INNER JOINこれには、 をLEFT OUTER JOIN?に変更する必要があると思います。

したがって、上記を考えると、最終的な結果は次のようになります。

ここに画像の説明を入力


編集

Bogdan の優れたヘルプのおかげで、次のものが得られました。
指定されたプレーヤー全体の合計である追加の合計 AmountGroup を追加しました。これは単に「あると便利」であり、元の仕様の一部ではありません。

DECLARE @NumDays INT = 3;

WITH    basic_cte AS
        (
        SELECT  rn = ROW_NUMBER() OVER(PARTITION BY Name ORDER BY x.DateKey),
                x.DateKey,
                d.Name,
                Amount      = ISNULL(f.Amount,0),
                AmountGroup = ISNULL(f.AmountGroup,0),
                AmountAll   = ISNULL(f.AmountAll,0)
        FROM    (
                SELECT  t.*, 
                EndLiveKey = CONVERT(INT,CONVERT(CHAR(8),CONVERT(DATETIME,CONVERT(DATETIME,CONVERT(CHAR(8),t.LiveKey,112))+@NumDays),112))
                FROM    #target t
                ) d 
                CROSS APPLY
                    (
                SELECT  dm.DateKey
                FROM    WHData.dbo.vw_DimDate dm
                WHERE   dm.DateKey >= d.LiveKey AND
                        dm.DateKey < d.EndLiveKey           
                ) x
                OUTER APPLY
                (
                SELECT  Amount  = SUM(CASE WHEN PlayerKey1 = PlayerKey2 THEN fbase.Amount END),
                        AmountGroup = SUM(CASE WHEN inGroup = 1 THEN fbase.Amount ELSE 0 END),
                        AmountAll   = SUM(fbase.Amount)
                FROM
                    (
                    SELECT  fct.Amount, 
                            fct.PlayerKey AS PlayerKey1, 
                        d.PlayerKey AS PlayerKey2,
                        CASE WHEN tt.PlayerKey IS NULL THEN 0 ELSE 1 END AS inGroup
                    FROM    #Fact fct 
                        LEFT OUTER JOIN #target tt ON
                        fct.PlayerKey = tt.PlayerKey 
                    WHERE   fct.DateKey = x.DateKey
                ) fbase
            ) f
        )
SELECT   y.*,
        "RollingAmount"     = SUM(Amount) OVER(PARTITION BY Name ORDER BY DateKey),
        "RollingAmountGroup"  = SUM(AmountGroup) OVER(PARTITION BY Name ORDER BY DateKey),
        "RollingAmountAll"  = SUM(AmountAll) OVER(PARTITION BY Name ORDER BY DateKey)
FROM    basic_cte y;
4

1 に答える 1