This question has been asked multiple times on SO but all the answers refer to SQL 2005 or later (e.g. OUTER APPLY
) and we are still using SQL 2000 (for corporate reasons too complex to go into here!)
I have a table of Things
and a table of Widgets
with a 0 to Many relationship:
CREATE TABLE Things ( ThingId INT, ThingName VARCHAR(50) )
CREATE TABLE Widgets ( WidgetId INT, ThingId INT, WidgetName VARCHAR(50) )
INSERT INTO Things VALUES ( 1, 'Thing 1' )
INSERT INTO Things VALUES ( 2, 'Thing 2' )
INSERT INTO Things VALUES ( 3, 'Thing 3' )
INSERT INTO Widgets VALUES ( 1, 2, 'Thing 2 Widget 1' )
INSERT INTO Widgets VALUES ( 2, 2, 'Thing 2 Widget 2' )
INSERT INTO Widgets VALUES ( 3, 3, 'Thing 3 Widget 1' )
A standard LEFT OUTER JOIN
returns the expected 4 rows
SELECT * FROM Things t LEFT OUTER JOIN Widgets w ON t.ThingId = w.ThingId
ThingId | ThingName | WidgetId | ThingId | WidgetName
---------+-----------+----------+---------+------------------
1 | Thing 1 | NULL | NULL | NULL
2 | Thing 2 | 1 | 2 | Thing 2 Widget 1
2 | Thing 2 | 2 | 2 | Thing 2 Widget 2
3 | Thing 3 | 3 | 3 | Thing 3 Widget 1
However, I only want the newest Widget for each Thing, i.e.:
ThingId | ThingName | WidgetId | ThingId | WidgetName
---------+-----------+----------+---------+------------------
1 | Thing 1 | NULL | NULL | NULL
2 | Thing 2 | 2 | 2 | Thing 2 Widget 2
3 | Thing 3 | 3 | 3 | Thing 3 Widget 1
My starting point was:
SELECT * FROM Things t LEFT OUTER JOIN (SELECT TOP 1 * FROM Widgets subw WHERE subw.ThingId = t.ThingId ORDER BY subw.WidgetId DESC) w ON t.ThingId = w.ThingId
But this is not valid because the parent t.ThingId
does not exist in the sub query.
Can this be achieved using SQL 2000?
If (ThingId, WidgetId)
combination is unique in table Widgets
, then this will work correctly:
SELECT t.*, w.*
FROM
dbo.Things AS t
LEFT OUTER JOIN
( SELECT ThingId, MAX(WidgetId) AS WidgetId
FROM dbo.Widgets
GROUP BY ThingId
) AS
subw
ON subw.ThingId = t.ThingId
LEFT OUTER JOIN
dbo.Widgets AS w
ON w.ThingId = subw.ThingId
AND w.WidgetId = subw.WidgetId ;