我有两个表(成员和活动),我正在尝试使用每个成员的最新活动查询成员。我已经使用了两个查询(一个用于获取成员,第二个用max(id)和group by(成员)在活动上)和一些代码来合并数据。我确定它可以通过一个查询来完成,但我无法完成它。有什么想法吗?
会员表
id, name
1, Shawn
2, bob
3, tom
活动表
id, member_id, code, timestamp, description
1, 1, 123, 15000, baked a cake
2, 1, 456, 20000, ate dinner
3, 2, 789, 21000, drove home
4, 1, 012, 22000, ate dessert
期望的结果:
id, name, activity_code, activity_timestamp, activity_description
1, shawn, 012, 22000, ate dessert
2, bob, 789, 21000, drove home
3, tom, null, null, null
答案 0 :(得分:28)
"每组最新" SQL中常见的问题是非常。仅在这个网站上有无数解决这个问题的例子。
如果您的时间戳是每个成员活动的唯一时间:
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)
或者,如果您的活动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子句将删除LEFT JOIN添加的行,从而有效地给出与原始INNER JOIN相同的结果。
但是如果在连接条件中应用附加谓词,则LEFT JOIN将按预期工作。
答案 1 :(得分:6)
SELECT
members.id ,
members.name,
activities.code AS activity_code,
activities.timestamp AS activity_timestamp,
activities.description AS activity_description
FROM
members
LEFT JOIN activities
ON members.id = activities.member_id
LEFT JOIN
(
SELECT
activities.member_id
MAX(activities.id) AS id
FROM activities
GROUP BY
activities.member_id
) AS t1
ON activities.id = t1.id
WHERE
t1.id IS NOT NULL
答案 2 :(得分:1)
Select max(a.id), m.name, a.activity_code, a.activity_timestamp, a.activity_description
From members m
Left join
activities a on a.member_id=m.id
Group by m.name, a.activity_code, a.activity_timestamp, a.activity_description