Reputation: 455
In a Microsoft SQL Server, we have this table which logs property changes of users:
ID | userID | prop | changeDate
-------------------------------
4 23 B 2017-02-18
1 14 D 2013-05-19
2 15 C 2014-04-10
3 23 A 2016-01-11
What I would like to do is to query this table and find the active property within a range of dates.
For instance the period of 2016-08-01
to 2017-01-01
I would like to get userID 23
with prop A
because that was the active property for that user until it was changed on 2017-02-18
I started out with the changeDate BETWEEN '2016-08-01' and '2017-01-01'
but that only covers those cases where I have the exact start date.
I'm turning slightly insane. Is this quest even possible with this data? Or maybe I am asking the wrong question?
Upvotes: 0
Views: 70
Reputation: 710
A self join can help here.
CREATE TABLE x (ID INT, userID INT, prop CHAR(1), changeDate DATETIME)
INSERT INTO x
VALUES ( 4, 23, 'B', '20170218' ),
( 1, 14, 'D', '20130519' ),
( 2, 15, 'C', '20140410' ),
( 3, 23, 'A', '20160111' )
; WITH cte AS (
SELECT x1.userID, x1.prop, x1.changeDate AS StartDate, MIN(x2.changeDate) AS ExitDate
FROM x x1
LEFT OUTER JOIN x x2
ON x1.changeDate < x2.changeDate
GROUP BY x1.userID, x1.prop, x1.changeDate
)
SELECT *
FROM cte
WHERE Startdate > = '20160801'
AND ( ExitDate IS NULL OR ExitDate < '20170101' )
This gives you what you are looking for
userID | prop | StartDate | ExitDate
--------------------------------------------------
23 B 2017-02-18 00:00:00.000 NULL
Upvotes: 1
Reputation: 1271231
For a table of this type, the typical question is "What was a given users property as-of a particular date?"
This answers that question:
select pc.*
from (select pc.*,
row_number() over (partition by userId order by changeDate desc) as seqnum
from propertychanges pc
where changeDate <= @AsOfDate
) pc
where seqnum = 1;
Upvotes: 2