私のテーブルは次のようになります:
CREATE TABLE [dbo].[TimeSeries](
[LOCID] [int] NOT NULL,
[Date] DateTime,
[YEAR] int,
[MONTH] tinyint,
[RTT] [int]
PRIMARY KEY ( [LOCID] ASC,[Date] ASC)
)
これには、LOCIDごと、年ごとに12行(またはMONTHS)が含まれます。
次のクエリがあります。
SELECT
LOCID,
[Year],
[Date],
AVG(cast(RTT as float)) OVER (
PARTITION BY LOCID ORDER BY Date
ROWS BETWEEN CURRENT ROW AND 4 FOLLOWING ) AS avgRTT
FROM TimeSeries
データの例:
LOCID Date Year Month RTT
1 01/01/1982 1982 1 58
1 01/02/1982 1982 2 63
1 01/03/1982 1982 3 34
1 01/04/1982 1982 4 27
1 01/05/1982 1982 5 6
1 01/06/1982 1982 6 4
1 01/07/1982 1982 7 3
1 01/08/1982 1982 8 14
1 01/09/1982 1982 9 22
1 01/10/1982 1982 10 16
1 01/11/1982 1982 11 17
1 01/12/1982 1982 12 44
1 01/01/1983 1983 1 58
1 01/02/1983 1983 2 63
1 01/03/1983 1983 3 33
1 01/04/1983 1983 4 27
1 01/05/1983 1983 5 9
1 01/06/1983 1983 6 0
1 01/07/1983 1983 7 3
1 01/08/1983 1983 8 0
1 01/09/1983 1983 9 6
1 01/10/1983 1983 10 27
1 01/11/1983 1983 11 11
1 01/12/1983 1983 12 48
今、私は毎年のみ特定の月について上記のクエリを実行して、続く5つの日付/月/行の平均を計算しようとしています。ただし、MONTH値を指定するWHERE句は機能しません。これは、平均される数値に影響するためです。
何万ものLOCIDと何百万もの行に対してこれを行う必要があります。
私の質問は、「MONTH」の特定の値に対してのみ正しい移動平均を実行する方法があるかどうかです。これにより、うまくいけば、処理時間を何度も短縮できます...
望ましい出力例:
LOCID Date Year Month avgRTT
1 29952 1982 1 37.6
1 30317 1983 1 38
どんなポインタでも大歓迎です。
移動平均を計算した後、_@dekade
_に最終フィルターを適用できます。
移動平均のために処理する必要のある行の数を減らすために、[dekade] IN (@dekade, (@dekade+1)%36, (@dekade+2)%36)
に以前のフィルターを適用して、最小限の行を処理しながら確実にすべての行を含めることができます。次の11行を移動平均に含める必要があります。 (_% 36
_の唯一の理由は、年末に該当する_@dekade
_の値を処理するためです。)
これにより、現在のテーブル構造が与えられた場合でもテーブルスキャンは行われますが、少なくともクエリプランの早い段階で行を除外できます。
_DECLARE @dekade TINYINT = 1
SELECT *
FROM (
SELECT
LOCID,
[Year],
[Date],
[dekade],
AVG(cast(RTT as float)) OVER
(PARTITION BY LOCID ORDER BY Date
ROWS BETWEEN CURRENT ROW AND 11 FOLLOWING) AS avgRTT
FROM TimeSeries
-- If you want to limit the rows that are use when computing the running average,
-- you can make sure that only the desired @dekade plus the following two @dekades
-- (which may be needed to get the following 11 rows) are used for each year
WHERE [dekade] (@dekade, (@dekade+1)%36, (@dekade+2)%36)
) x
-- Filter your results be @dekade after computing the running average
WHERE x.[dekade] = @dekade
_
実際にクエリを実行できるように、いくつかのサンプルデータを投稿すると役立ちます。
運が良ければ、オプティマイザが年に1回だけ移動平均を計算できるほど賢い場合は、AVG
をCASE
に入れてみてください。
select *
from
(
SELECT
LOCID,
[Year],
[Date],
[Month],
case when Month = 1 then
AVG(cast(RTT as float)) OVER (
PARTITION BY LOCID ORDER BY Date
ROWS BETWEEN CURRENT ROW AND 4 FOLLOWING )
end AS avgRTT
FROM TimeSeries
) as dt
where month = 1 -- or avgRTT is not null