Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

MySQL LEFT JOIN usando MAX &GROUP BY na tabela unida?


O problema do "último por grupo" é extremamente comum em SQL. Existem inúmeros exemplos de soluções para este problema apenas neste site.

Se seus timestamps são únicos por atividade de membro:
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)

alternativamente, se o ID da sua atividade estiver aumentando monotonicamente com o tempo:
  ...
WHERE
  a.id = (SELECT MAX(id) FROM activities WHERE member_id = m.id)

Você não precisa agrupar. Mas a consulta se beneficiará de um índice em activities sobre (member_id, timestamp) ou (member_id, id) , respectivamente.

EDITAR

Para mostrar os membros que não registraram uma atividade, use uma entrada à esquerda como esta.
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)

Observe que não há WHERE cláusula. Semanticamente, WHERE é aplicado depois as junções são feitas. Portanto, uma cláusula WHERE removeria as linhas que o LEFT JOIN adicionou, efetivamente fornecendo o mesmo resultado que o INNER JOIN original.

Mas se você aplicar o predicado adicional diretamente na condição de junção, o LEFT JOIN funcionará conforme o esperado.