简体   繁体   中英

SQL Join to the latest record in MS ACCESS

I want to join tables in MS Access in such a way that it fetches only the latest record from one of the tables. I've looked at the other solutions available on the site, but discovered that they only work for other versions of SQL. Here is a simplified version of my data:

PatientInfo Table:

    +-----+------+
    | ID  | Name |
    +-----+------+
    |  1  | John |
    |  2  | Tom  |
    |  3  | Anna |
    +-----+------+

Appointments Table

    +----+-----------+
    | ID |   Date    |
    +----+-----------+
    |  1 | 5/5/2001  |
    |  1 | 10/5/2012 |
    |  1 | 4/20/2018 |
    |  2 | 4/5/1999  |
    |  2 | 8/8/2010  |
    |  2 | 4/9/1982  |
    |  3 | 7/3/1997  |
    |  3 | 6/4/2015  |
    |  3 | 3/4/2017  |
    +----+-----------+

And here is a simplified version of the results that I need after the join:

    +----+------+------------+
    | ID | Name |    Date    |
    +----+------+------------+
    |  1 | John |  4/20/2018 |
    |  2 | Tom  |  8/8/2010  |
    |  3 | Anna |  3/4/2017  |
    +----+------+------------+

Thanks in advance for reading and for your help.

You can use aggregation and JOIN :

select pi.id, pi.name, max(a.date)
from appointments as a inner join
     patientinfo as pi
     on a.id = pi.id
group by pi.id, pi.name;

something like this: select P.ID, P.name, max(A.Date) as Dt from PatientInfo P inner join Appointments A on P.ID=A.ID group by P.ID, P.name

Both Bing and Gordon's answers work if your summary table only needs one field (the Max(Date)) but gets more tricky if you also want to report other fields from the joined table, since you would need to include them either as an aggregated field or group by them as well. Eg if you want your summary to also include the assessment they were given at their last appointment, GROUP BY is not the way to go.

A more versatile structure may be something like

SELECT Patient.ID, Patient.Name, Appointment.Date, Appointment.Assessment
FROM Patient INNER JOIN Appointment ON Patient.ID=Appointment.ID
WHERE Appointment.Date = (SELECT Max(Appointment.Date) FROM Appointment WHERE Appointment.ID = Patient.ID)
;

As an aside, you may want to think whether you should use a field named 'ID' to refer to the ID of another table (in this case, the Apppintment.ID field refers to the Patient.ID). You may make your db more readable if you leave the 'ID' field as an identifier specific to that table and refer to that field in other tables as OtherTableID or similar, ie PatientID in this case. Or go all the way and include the name of the actual table in its own ID field.

Edited after comment:

Not quite sure why it would crash. I just ran an equivalent query on 2 tables I have which are about 10,000 records each and it was pretty instanteneous. Are your ID fields (i) unique numbers and (ii) indexed? Another structure which should do the same thing (adapted for your field names and assuming that there is an ID field in Appointments which is unique) would be something like:

SELECT PatientInfo.UID, PatientInfo.Name, Appointments.StartDateTime, Appointments.Assessment
FROM PatientInfo INNER JOIN Appointments ON PatientInfo_UID = Appointments.PatientFID
WHERE Appointments.ID = (SELECT TOP 1 ID FROM Appointments WHERE Appointments.PatientFID = PatientInfo_UID ORDER BY StartDateTime DESC)
;

But that is starting to look a bit contrived. On my data they both produce the same result (as they should.) and are both almost instantaneous? Always difficult to troubleshoot Access when it crashes - I guess you see no error codes or similar. Is this against a native?accdb database or another server?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM