My sample database (in fact a CTE statement data) looks like this:
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
I want to remove the values that are less than 12 in difference. This is my query and output:
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
Output:
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
The problem is that it compares between current and previous row. I need to compare between current and previous non-NULL value, I mean the last value that was not NULLed on the previous step.
This is what I need:
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
I tried the following.
I made a self-referenced CTE query as above replacing THEN NULL
with THEN LAG(val) OVER (ORDER BY eventdate)
to copy last appropriate value and compare with next. Then remove duplicates. But it deadly loops on OPTION (MAXRECURSION 0)
with no results at all.
Seems this could be done by CURSOR only.
I need the result set as CTE statement (within the CTE), to use it in next query.
As far as I looked for CURSOR examples they all are done as a final SELECT
to CTE.
This is not an option for me!
I am running SQL Server 2014.
Many thanks for your help or thoughts!
Best Answer
Here is a recursive CTE solution using a technique that Paul White blogged about in Performance Tuning the Whole Query Plan.