I have two tables: TableA (ID [int, pk], Name [string]) and TableB (ID [int, pk], TableA_ID [int, fk], Name [string], DateStamp [datetime (dd/mm/yyyy hh:MM:ss)]). There is a one-to-many relationship between TableA and TableB.
An inner join on the two tables will give me the following results:
TableA.ID, TableA.Name, TableB.Name, TableB.DateStamp 1, 'File A', 'Version 1', 01/01/2009 15:00:00 1, 'File A', 'Version 2', 05/01/2009 08:15:00 1, 'File A', 'Version 3', 06/01/2009 19:33:00 2, 'File B', 'Version 1', 03/01/2009 09:10:00 2, 'File B', 'Version 2', 20/01/2009 20:00:00 3, 'File C', 'Version 1', 01/01/2009 17:00:00
What I actually want is the following (each row from TableA and the last matching row from TableB):
TableA.ID, TableA.Name, TableB.Name, TableB.DateStamp 1, 'File A', 'Version 3', 06/01/2009 19:33:00 2, 'File B', 'Version 2', 20/01/2009 20:00:00 3, 'File C', 'Version 1', 01/01/2009 17:00:00
This is the query that I’m using to achieve this:
SELECT ta.ID, ta.Name, tb.Name, tb.DateStamp FROM TableA ta INNER JOIN TableB tb ON ta.ID = tb.TableA_ID WHERE tb.ID IN ( SELECT TOP 1 tb2.ID FROM TableB tb2 WHERE tb2.TableA_ID = ta.ID ORDER BY tb2.DateStamp DESC)
That works but my gut feeling is that I’m not doing this in the ‘best way’. It looks like it is a candidate for an aggregation query (i.e. groupby) but I didn’t have any luck with that. In the end I always had to use a subquery to get the row I’m after in TableB.
Any help much appreciated.
No, there is no requirement to do GROUP BY here, this should be solved through a correlated sub-query:
An additional GROUP BY is only necessary if you have more than one record in
TableBwith equalTableA_IDand equalDateStamp.For the specific example you’ve shown, a GROUP BY query happens to produce the correct result. It’s still wrong, because the correct result is more a side-effect in this situation.
This relies on the coincidence that
MAX(TableB.Name)is in fact the value you want to get out, and it is aligned withMAX(TableB.DateStamp). But since this correlation is a mere accident, the GROUP BY query is wrong.