Some help with some T-SQL would be most appreciated.
I have the following four tables:
- Item (Id)
- ItemVersion (Id, FK many-to-one Item.Id)
- ItemVersionStatusLog (LogDate, FK many-to-one ItemVersion.Id, FK many-to-one StatusType.Id)
- StatusType (Id, Alias)
I’ve only listed the columns appropriate to this question.
The root entity is an Item. For each Item, there is one or more ItemVersion entries. For each ItemVersion entry, there is one or more ItemVersionStatusLog entries with a date and a reference to a StatusType (e.g. created, updated, disabled).
I’d like to summarise the “most recent status” of each Item by creating an aggregate view in a new table (ItemStatus) that I’ll backfill and then keep updated when data changes. The aggregation should give me the maximum-dated entry in the log table, for each Item and StatusType pair. So that I have a snapshot of, for each StatusType, I can get the most recent ItemVersion for an Item.
Another way of putting it is procedurally:
For each Item
- For each StatusType
- - List the ItemVersion Id with the maximum date from ItemVersionStatusLog given the correct StatusType
My target columns for the aggregate view or table are:
Item Id, ItemVersion Id, Date (from ItemVersionStatus), StatusType Id
While I could do this reasonably well with the use of UDF’s, if possible I’d love to do this in a single SQL statement. My primary target is SQL Server 2008, but also SQL Server Compact 4 without much modification, so relying on UDF’s isn’t a great option but any help is appreciated 🙂
Update – some example data
Item:
Id
--
1
2
ItemVersion:
Id | ItemId | Name
----------
1 | 1 | Apple
2 | 1 | Orange
3 | 1 | Plum
4 | 2 | Petrol
5 | 2 | Diesel
6 | 2 | LPG
StatusType:
Id | Alias
-----------
1 | Created
2 | Approved
3 | Published
4 | Deleted
ItemVersionStatusLog:
Id | ItemVersionId | StatusTypeId | Date
------------------------------------------
1 | 1 | 1 | 2012-01-01 00:00
2 | 1 | 4 | 2012-01-01 00:05
3 | 2 | 1 | 2012-01-01 00:10
4 | 2 | 3 | 2012-01-01 00:15
5 | 3 | 1 | 2012-01-01 00:20
6 | 3 | 3 | 2012-01-01 00:25
In this case the expected result for Item 1 would be:
ItemStatus
ItemId | ItemVersionId | Date | StatusTypeId
--------------------------------------------------------
1 | 3 | 2012-01-01 00:20 | 1
1 | 3 | 2012-01-01 00:25 | 3
1 | 1 | 2012-01-01 00:05 | 4
SQL Fiddle Version
A version that does not use a CTE:
SQL Fiddle Version
One catch with the above solution is that it does not allow for multiple entries for the same status on the same date and time. If we can assume that in the case of such a tie, that the last
ItemVersionStatusLog.Idvalue is to be used, then we would adjust like so:SQL Fiddle Version