Looking to do a LAG/LAST_VALUE/MAGIC window function on a table which somehow needs to include a date filter (as in how far back it should go). I’m trying to get the value as of 7 days ago onto every row. Not sure this can be achieved with a fancy window function in a sparse data set. As the data is quite large, it would need to be an efficient query query as well.
Test Query (wrong result):
x
WITH TestData AS (
SELECT 'MyKey' AS KeyCol, CAST('2019-05-06' AS DATE) as DateCol, 20 as ValueCol
UNION ALL
SELECT 'MyKey' AS KeyCol, CAST('2019-05-12' AS DATE) as DateCol, 12 as ValueCol
UNION ALL
SELECT 'MyKey' AS KeyCol, CAST('2019-06-01' AS DATE) as DateCol, 41 as ValueCol
UNION ALL
SELECT 'MyKey' AS KeyCol, CAST('2019-06-14' AS DATE) as DateCol, 21 as ValueCol
UNION ALL
SELECT 'MyKey' AS KeyCol, CAST('2019-06-15' AS DATE) as DateCol, 2 as ValueCol
UNION ALL
SELECT 'MyKey' AS KeyCol, CAST('2019-06-20' AS DATE) as DateCol, 32 as ValueCol
)
SELECT KeyCol, DateCol, ValueCol
, LAG(ValueCol) OVER (ORDER BY DateCol ASC) ThisShouldShowValueAsOf7DaysAgo
from TestData
Output:
+--------+------------+----------+---------------------------------+
| KeyCol | DateCol | ValueCol | ThisShouldShowValueAsOf7DaysAgo |
+--------+------------+----------+---------------------------------+
| MyKey | 2019-05-06 | 20 | NULL |
| MyKey | 2019-05-12 | 12 | 20 -> should be NULL |
| MyKey | 2019-06-01 | 41 | 12 -> correct |
| MyKey | 2019-06-14 | 21 | 41 -> correct |
| MyKey | 2019-06-15 | 2 | 21 -> should be 41 |
| MyKey | 2019-06-20 | 32 | 2 -> should be 41 |
+--------+------------+----------+---------------------------------+
Advertisement
Answer
I think you want apply
:
select t.*, t2.valuecol
from t outer apply
(select top (1) t2.*
from t t2
where t2.keycol = t.keycol and
t2.date < dateadd(day, -7, t.date)
order by t2.date desc
) t2
In other databases, you could use a fancy window frame with range between
. However, SQL Server does not support such functionality.