Excuse the long question!
We have two database tables, e.g. Car and Wheel. They are related in that a wheel belongs to a car and a car has multiple wheels. The wheels, however, can be changed without affecting the "version" of the car. The car's record can be updated (e.g. paint job) without affecting the version of the wheels (i.e. no cascade updating).
For example, Car table currently looks like this:
CarId, CarVer, VersionTime, Colour
1 1 9:00 Red
1 2 9:30 Blue
1 3 9:45 Yellow
1 4 10:00 Black
The Wheels table looks like this (this car only has two wheels!)
WheelId, WheelVer, VersionTime, CarId
1 1 9:00 1
1 2 9:40 1
1 3 10:05 1
2 1 9:00 1
So, there's been 4 versions of this two wheeled car. It's first wheel (WheelId 1) hasn't changed. The second wheel was changed (e.g. painted) at 10:05.
How do I efficiently do as of queries that can be joined to other tables as required? Note that this is a new database and we own the schema and can change it or add audit tables to make this query easier. We've tried one audit table approach (with columns: CarId, CarVersion, WheelId, WheelVersion, CarVerTime, WheelVerTime), but it didn't really improve our query.
Example query: Show the Car ID 1 as it was, including its wheel records as of 9:50. This query should result in these two rows being returned:
WheelId, WheelVer, WheelVerTime, CarId, CarVer, CarVerTime, CarColour
1 2 9:40 1 3 9:45 Yellow
2 1 9:00 1 3 9:45 Yellow
The best query we could come up with was this:
select c.CarId, c.VersionTime, w.WheelId,w.WheelVer,w.VersionTime,w.CarId
from Cars c,
( select w.WheelId,w.WheelVer,w.VersionTime,w.CarId
from Wheels w
where w.VersionTime <= "12 Jun 2009 09:50"
group by w.WheelId,w.CarId
having w.WheelVer = max(w.WheelVer)
) w
where c.CarId = w.CarId
and c.CarId = 1
and c.VersionTime <= "12 Jun 2009 09:50"
group by c.CarId, w.WheelId,w.WheelVer,w.VersionTime,w.CarId
having c.CarVer = max(c.CarVer)
And, if you wanted to try this then the create table and insert record SQL is here:
create table Wheels
(
WheelId int not null,
WheelVer int not null,
VersionTime datetime not null,
CarId int not null,
PRIMARY KEY (WheelId,WheelVer)
)
go
insert into Wheels values (1,1,'12 Jun 2009 09:00', 1)
go
insert into Wheels values (1,2,'12 Jun 2009 09:40', 1)
go
insert into Wheels values (1,3,'12 Jun 2009 10:05', 1)
go
insert into Wheels values (2,1,'12 Jun 2009 09:00', 1)
go
create table Cars
(
CarId int not null,
CarVer int not null,
VersionTime datetime not null,
colour varchar(50) not null,
PRIMARY KEY (CarId,CarVer)
)
go
insert into Cars values (1,1,'12 Jun 2009 09:00', 'Red')
go
insert into Cars values (1,2,'12 Jun 2009 09:30', 'Blue')
go
insert into Cars values (1,3,'12 Jun 2009 09:45', 'Yellow')
go
insert into Cars values (1,4,'12 Jun 2009 10:00', 'Black')
go