MySQL LEFT JOIN在连接表上使用MAX&GROUP BY?

Sha*_*ide 22 mysql

我有两个表(成员和活动),我正在尝试使用每个成员的最新活动查询成员.我已经使用了两个查询(一个用于获取成员,第二个用max(id)和group by(成员)在活动上)和一些代码来合并数据.我确定它可以通过一个查询来完成,但我无法完成它.有任何想法吗?

会员表

id, name
 1, Shawn
 2, bob
 3, tom
Run Code Online (Sandbox Code Playgroud)

活动表

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
Run Code Online (Sandbox Code Playgroud)

期望的结果:

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
Run Code Online (Sandbox Code Playgroud)

Tom*_*lak 29

"每组最新"问题在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)
Run Code Online (Sandbox Code Playgroud)

或者,如果您的活动ID随时间单调增加:

  ...
WHERE
  a.id = (SELECT MAX(id) FROM activities WHERE member_id = m.id)
Run Code Online (Sandbox Code Playgroud)

你不需要分组.但是查询将分别受到activitiesover (member_id, timestamp)或index的索引的影响(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)
Run Code Online (Sandbox Code Playgroud)

请注意,没有WHERE条款.在语义上,完成连接之后应用WHERE .因此,WHERE子句将删除LEFT JOIN添加的行,从而有效地给出与原始INNER JOIN相同的结果.

但是如果在连接条件中应用附加谓词,则LEFT JOIN将按预期工作.


edz*_*dze 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
Run Code Online (Sandbox Code Playgroud)