Reputation: 3688
I imagine this has been done many time before but I can't for the life of me figure it out and I am tired of trying work arounds.
I have two tables.
One is an Object having ObjectID(key), Name, Type, Location
Two is ObjectStatus having StatusID(key),ObjectID,Status,DateChanged,UserWhoChangedStatus
What I want to do is return all Objects and the ObjectStatus that was entered last
Table 1 Object
ObjectID Name Type Location
1 Blue Ball Ball ToyBox
2 Red Ball Ball ToyBox
Table 2 (ObjectStatus)
StatusID ObjectID Status DateChanged UserWhoChangedStatus
1 2 Broken 2012-01-25 56481
2 2 Fixed 2012-01-30 98526
3 1 Bouncy 2012-01-05 85245
4 1 Sticky 2012-02-10 56481
I would want to get returned
ObjectID Name Type Location StatusID Status DateChanged UserWhoChangedStatus
1 Blue Ball Ball ToyBox 4 Sticky 2012-02-10 56481
2 RedBall Ball ToyBox 2 Fixed 2012-01-30 98526
Which is all Objects and the ObjectStatus that was last entered
Upvotes: 3
Views: 906
Reputation: 70523
There are a number of way to do this but I like the the following way because it seems most intuitive -- it uses a CTE and left joins which makes it simpler if the query gets more complicated:
WITH maxDate AS
(
SELECT objectID, MAX(DateChanged) AS maxDate
FROM ObjectStatus
GROUP BY objectID
)
SELECT O.*, OS.*
FROM Object O
LEFT JOIN maxDate ON maxDate.objectID = O.ObjectID
LEFT JOIN ObjectStatus ON OS.ObjectID = O.ObjectID
AND OS.DateChanged = maxDate.maxDate
Upvotes: 0
Reputation:
Just to provide an alternate solution so future readers can compare performance and pick the appropriate method in their case.
;WITH LastChange AS
(
SELECT
ObjectID, Status, DateChanged, UserWhoChangedStatus,
rn = ROW_NUMBER() OVER (PARTITION BY ObjectID ORDER BY DateChanged DESC)
FROM dbo.ObjectStatus
)
SELECT
o.ObjectID, o.Name, o.Type, o.Location,
l.StatusID, l.Status, l.DateChanged, l.UserWhoChangedStatus
FROM dbo.Object AS o
LEFT OUTER JOIN LastChange AS l
ON o.ObjectID = l.ObjectID
AND l.rn = 1;
You can change the LEFT OUTER JOIN
to INNER JOIN
if you somehow know that the status table will always have at least one row for every ObjectID
, or if you don't want to return objects that don't have a row in status.
Upvotes: 1
Reputation: 50201
Since you didn't say the DBMS I will assume Ms Sql Server.
SELECT
O.*,
S.*
FROM
dbo.Object O
OUTER APPLY (
SELECT TOP 1 *
FROM dbo.ObjectStatus S
WHERE O.ObjectID = S.ObjectID
ORDER BY DateChanged DESC
) S
Upvotes: 3