Ответ 1
Проблема "последняя для каждой группы" чрезвычайно распространена в SQL. Существует множество примеров решений этой самой проблемы только на этом сайте.
Если ваши временные метки являются uniqe для активности каждого члена:
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)
в качестве альтернативы, если ваш идентификатор активности увеличивается монотонно со временем:
...
WHERE
a.id = (SELECT MAX(id) FROM activities WHERE member_id = m.id)
Вам не нужно группировать. Но запрос будет полезен из индекса на activities
над (member_id, timestamp)
или (member_id, id)
, соответственно.
ИЗМЕНИТЬ
Чтобы показать участников, которые не зарегистрировали действие, используйте левое соединение, подобное этому.
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)
Обратите внимание, что нет предложения WHERE
. Семантически, WHERE применяется после завершения объединений. Таким образом, предложение WHERE будет удалять строки, добавленные в LEFT JOIN, что дает тот же результат, что и исходный INNER JOIN.
Но если вы примените дополнительное предикатное право в условии соединения, LEFT JOIN будет работать как ожидалось.