私は現在、次のようなデータを持っています(ただし、より大きくなります!)
/*--:::::::::::
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;