Mysql
 sql >> Database >  >> RDS >> Mysql

MySQL LEFT JOIN usando MAX &GROUP BY su una tabella unita?

Il problema dell'"ultimo per gruppo" è estremamente comune in SQL. Ci sono innumerevoli esempi di soluzioni a questo stesso problema solo su questo sito.

Se i tuoi timestamp sono unici per attività del 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)

in alternativa, se il tuo ID attività aumenta in modo monotono con il tempo:

  ...
WHERE
  a.id = (SELECT MAX(id) FROM activities WHERE member_id = m.id)

Non è necessario raggruppare. Ma la query trarrà vantaggio da un indice su activities su (member_id, timestamp) o (member_id, id) , rispettivamente.

MODIFICA

Per mostrare tutti i membri che non hanno registrato un'attività, usa un join sinistro come questo.

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)

Nota che non c'è WHERE clausola. Semanticamente, WHERE viene applicato dopo le giunzioni sono fatte. Quindi una clausola WHERE rimuoverebbe le righe aggiunte da LEFT JOIN, dando effettivamente lo stesso risultato dell'INNER JOIN originale.

Ma se applichi il predicato aggiuntivo direttamente nella condizione di unione, LEFT JOIN funzionerà come previsto.