| Author |
Topic |
|
adam2k1
Starting Member
6 Posts |
Posted - 2009-03-16 : 07:30:12
|
| Heya, i have a (probably) straight forward question regarding a SQL query:What i want is to take every record in a table (tblReferral), and join to the LATEST RECORD ONLY on another (tblNameHistory), also to the LATEST RECORD ONLY on a 3rd (tblAddressHistory). I've added the table structures below to illustrate my question:tblReferralReferralID (PK) | PersonID (FK) | field11 | 1 | anything2 | 1 | something3 | 2 | nothing...tblNameHistoryPersonID (PK) | Forename | Surname | dtStart | dtEnd1 | John | Smith | 01/01/01 | 02/02/021 | John | Jones | 02/02/02 | 03/03/032 | Paul | Black | 01/01/01 | NULL...tblAddressHistoryPersonID (PK) | AddrLine1 | AddrLine2 | dtStart | dtEnd1 | 1 Main Street | Leeds | 01/01/01 | 02/02/021 | 1 Small Street | Leeds | 02/02/02 | NULL2 | 3 Little Lane | Leeds | 01/01/01 | NULL...Below is the desired outputReferralID | PersonID | Forename | Surname | AddrLine1 | AddrLine2 | field11 | 1| John | Jones | 1 Small Street | Leeds | anything2 | 1| John | Jones | 1 Small Street | Leeds | something3 | 2| Paul | Black | 1 Small Street | Leeds | nothing...And the query i have is:SELECT tblReferral.ReferralID, tblReferral.PersonID, (SELECT TOP 1 Forename FROM tblNameHistory WHERE tblNameHistory.PersonID = tblReferral.PersonID) Forename, (SELECT TOP 1 Surname FROM tblNameHistory WHERE tblNameHistory.PersonID = tblReferral.PersonID) Surname, (SELECT TOP 1 AddrLine1 FROM tblAddressHistory WHERE tblAddressHistory.PersonID = tblReferral.PersonID) AddrLine1, (SELECT TOP 1 AddrLine2 FROM tblAddressHistory WHERE tblAddressHistory.PersonID = tblReferral.PersonID) AddrLine2, tblReferral.field1,FROM tblReferralThis works, but I'm confident there is a better, more efficient query that i could use. Any suggestions would be appreciated.Thanks,Adam |
|
|
sakets_2000
Master Smack Fu Yak Hacker
1472 Posts |
Posted - 2009-03-16 : 08:09:06
|
| Your query doesn't account for the latest start date. I don't think what you have is right. |
 |
|
|
sakets_2000
Master Smack Fu Yak Hacker
1472 Posts |
Posted - 2009-03-16 : 08:10:51
|
You can edit your query to this to account for startdate, SELECT tblReferral.ReferralID,tblReferral.PersonID,(SELECT TOP 1 Forename FROM tblNameHistory WHERE tblNameHistory.PersonID = tblReferral.PersonID order by startdt desc) Forename,(SELECT TOP 1 Surname FROM tblNameHistory WHERE tblNameHistory.PersonID = tblReferral.PersonID order by startdt desc) Surname,(SELECT TOP 1 AddrLine1 FROM tblAddressHistory WHERE tblAddressHistory.PersonID = tblReferral.PersonID order by startdt desc) AddrLine1,(SELECT TOP 1 AddrLine2 FROM tblAddressHistory WHERE tblAddressHistory.PersonID = tblReferral.PersonID order by startdt desc) AddrLine2,tblReferral.field1FROM tblReferral |
 |
|
|
sakets_2000
Master Smack Fu Yak Hacker
1472 Posts |
Posted - 2009-03-16 : 08:12:11
|
Or you can re-write it to this for better performance,SELECT a.ReferralID, a.PersonID, b.Forename, b.Surname, c.AddrLine1, c.AddrLine2, a.field1FROM tblReferral a join (select personid,max(dtStart) as MaxDt from tblNameHistory group by personid)b on a.personId=b.personId and b.MaxDt=a.dtStart join (select personid,max(dtStart) as MaxDt from tblAddressHistory group by personid)c on a.personId=c.personId and c.MaxDt=a.dtStart |
 |
|
|
adam2k1
Starting Member
6 Posts |
Posted - 2009-03-16 : 08:18:06
|
| Sorry, that was a error in posting. my original query did include the ordering.My problem though isn't with this query (or even your amended one, thanks) - I know that works and it returns the data I want.The issue I have is that I suspect it's not very efficient and there is a better query i could use. Can anyone confirm if this is correct, and if so provide an alternative?Thanks |
 |
|
|
adam2k1
Starting Member
6 Posts |
Posted - 2009-03-16 : 08:20:46
|
| Cheers, Thats what I was looking for - a way to join on a one-to-many but only look at the latest record.Adam |
 |
|
|
matty
Posting Yak Master
161 Posts |
Posted - 2009-03-16 : 08:22:56
|
| SELECT r.ReferralID,r.PersonID,nh.Forename,nh.Surname,ah.AddrLine1,ah.AddrLine2,r.field1FROM tblReferral rJOIN(SELECT PersonID,Forename,Surname,ROW_NUMBER() OVER(PARTITION BY PersonID ORDER BY dtStart DESC) AS Rownum FROM tblNameHistory) nhON nh.PersonID = r.PersonID AND nh.rownum = 1JOIN(SELECT PersonID,AddrLine1,AddrLine2,ROW_NUMBER() OVER(PARTITION BY PersonID ORDER BY dtStart DESC) AS Rownum FROM tblAddressHistory) ahON ah.PersonID = r.PersonID AND ah.rownum = 1 |
 |
|
|
sakets_2000
Master Smack Fu Yak Hacker
1472 Posts |
Posted - 2009-03-16 : 08:23:00
|
| Did you check the one posted @ 03/16/2009 : 08:12:11 ? |
 |
|
|
adam2k1
Starting Member
6 Posts |
Posted - 2009-03-16 : 09:18:49
|
| Thanks guys.i don't have a large dataset to test the queries against but I will have soon enough - cheers for the advice.Saket - started posting my response before I refreshed the page, so missed your 3rd post. |
 |
|
|
|