Reputation: 159
I'm sure this has been answered before but couldn't find it.
I have a table of items which change status every few weeks. I want to look at an arbitrary day and figure out how many items were in each status.
For example:
tbl_ItemHistory
ItemID
StatusChangeDate
StatusID
Sample data:
1001, 1/1/2010, 1
1001, 4/5/2010, 2
1001, 6/15/2010, 4
1002, 4/1/2010, 1
1002, 6/1/2010, 3
...
So I need to figure out how many items were in each status for a given day. So on 5/1/2010, there was one item (1001) in status 2 and one item in status 1 (1002).
Since these items don't change status very often, maybe I could create a cached table every night that has a row for every item and every day of the year? I'm not sure if that's best or how to do that though
I'm using SQL Server 2008R2
Upvotes: 1
Views: 3103
Reputation: 1271091
For an arbitrary day, you can do something like this:
select ih.*
from (select ih.*,
row_number() over (partition by itemId order by StatusChangeDate desc) as seqnum
from tbl_ItemHistory ih
where StatusChangeDate <= @YOURDATEGOESHERE
) ih
where seqnum = 1
The idea is to enumerate all the history records for each on or before the date,using row_nubmer
. The ordering is in reverse chronological order, so the most recent record -- on or before the date -- has a value of 1.
The query then just chooses the records whose value is 1.
To aggregate the results to get each status for the date, use:
select statusId, count(*)
from (select ih.*,
row_number() over (partition by itemId order by StatusChangeDate desc) as seqnum
from tbl_ItemHistory ih
where StatusChangeDate <= @YOURDATEGOESHERE
) ih
where seqnum = 1
group by StatusId
Upvotes: 3