Het "laatste per groep" probleem is extreem gebruikelijk in SQL. Alleen al op deze site zijn talloze voorbeelden van oplossingen voor dit probleem te vinden.
Als uw tijdstempels uniek zijn per ledenactiviteit:
SELECT
m.id,
m.name,
a.code activity_code,
a.timestamp activity_timestamp,
a.description activity_description
FROM
members m
INNER JOIN activities a ON a.member_id = m.id
WHERE
a.timestamp = (SELECT MAX(timestamp) FROM activities WHERE member_id = m.id)
als alternatief, als uw activiteits-ID in de loop van de tijd monotoon toeneemt:
...
WHERE
a.id = (SELECT MAX(id) FROM activities WHERE member_id = m.id)
Je hoeft niet te groeperen. Maar de zoekopdracht heeft baat bij een index op activities
over (member_id, timestamp)
of (member_id, id)
, respectievelijk.
BEWERKEN
Om leden te laten zien die geen activiteit hebben gelogd, gebruik je een left join zoals deze.
SELECT
m.id,
m.name,
a.code activity_code,
a.timestamp activity_timestamp,
a.description activity_description
FROM
members m
LEFT JOIN activities a ON
a.member_id = m.id
AND a.timestamp = (SELECT MAX(timestamp) FROM activities WHERE member_id = m.id)
Merk op dat er geen WHERE
. is clausule. Semantisch wordt WHERE toegepast na de koppelingen zijn gedaan. Dus een WHERE-clausule zou de rijen verwijderen die de LEFT JOIN heeft toegevoegd, wat in feite hetzelfde resultaat oplevert als de oorspronkelijke INNER JOIN.
Maar als u het aanvullende predikaatrecht toepast in de join-voorwaarde, werkt de LEFT JOIN zoals verwacht.