私のサンプルデータベース(実際にはCTEステートメントデータ)は次のようになります。
_eventdate val
2012-03-23 3965
2012-03-26 3979
2012-03-27 3974
2012-03-28 3965
2012-03-29 3967
2012-03-30 3959
2012-04-02 3951
2012-04-03 3961
2012-04-04 3944
2012-04-05 3935
2012-04-09 3901
2012-04-10 3822
_
差が12未満の値を削除したい。これは私のクエリと出力です:
_SELECT
eventdate,
CASE
WHEN ABS(val - LAG(val) OVER (ORDER BY eventdate)) <= 12
THEN NULL
ELSE val
END AS val
FROM tbl_1
ORDER BY eventdate
_
出力:
_eventdate val
2012-03-23 3965
2012-03-26 3979
2012-03-27 NULL
2012-03-28 NULL
2012-03-29 NULL
2012-03-30 NULL
2012-04-02 NULL
2012-04-03 NULL
2012-04-04 3944
2012-04-05 NULL
2012-04-09 3901
2012-04-10 3822
_
問題は、現在の行と前の行を比較することです。現在と以前の非NULL値を比較する必要があります。つまり、前のステップでNULLにされなかった最後の値を意味します。
これは私が必要なものです:
_eventdate val
2012-03-23 3965
2012-03-26 3979
2012-03-27 NULL
2012-03-28 3965
2012-03-29 NULL
2012-03-30 NULL
2012-04-02 3951
2012-04-03 NULL
2012-04-04 NULL
2012-04-05 3935
2012-04-09 3901
2012-04-10 3822
_
以下を試しました。上記のように自己参照CTEクエリを作成し、_THEN NULL
_をTHEN LAG(val) OVER (ORDER BY eventdate)
に置き換えて、最後の適切な値をコピーし、次の値と比較しました。次に、重複を削除します。しかし、それはOPTION (MAXRECURSION 0)
で致命的なループを起こし、結果はまったくありません。
これはCURSORだけで実行できるようです。次のクエリで使用するには、結果セットをCTEステートメント(CTE内)として必要です。
私がCURSORの例を探した限り、それらはすべてCTEへの最終的なSELECT
として行われます。これは私の選択肢ではありません!
SQL Server 2014を実行しています。
あなたの助けや考えに感謝します!
以下は、Paul Whiteがブログで取り上げた Performance Tuning the Whole Query Plan の手法を使用した再帰CTEソリューションです。
declare @T table
(
Eventdate date index IX_Eventdate clustered,
Val int
);
insert into @T(Eventdate, Val) values
('2012-03-23', 3965),
('2012-03-26', 3979),
('2012-03-27', 3974),
('2012-03-28', 3965),
('2012-03-29', 3967),
('2012-03-30', 3959),
('2012-04-02', 3951),
('2012-04-03', 3961),
('2012-04-04', 3944),
('2012-04-05', 3935),
('2012-04-09', 3901),
('2012-04-10', 3822);
with C as
(
select top(1)
T.Eventdate,
T.Val,
T.Val as PrevVal1,
T.Val as PrevVal2
from @T as T
order by T.eventdate
union all
select T.Eventdate,
T.Val,
T.PrevVal1,
T.PrevVal2
from (
select T.Eventdate,
T.Val,
iif(abs(T.Val - C.PrevVal1) <= 12, C.PrevVal1, T.Val) as PrevVal1,
iif(abs(T.Val - C.PrevVal1) <= 12, null, T.Val) as PrevVal2,
row_number() over(order by T.Eventdate) as rn
from @T as T
inner join C
on C.Eventdate < T.Eventdate
) as T
where T.rn = 1
)
select C.Eventdate,
C.PrevVal2 as Val
from C
order by C.Eventdate
option (maxrecursion 0);