sql >> Database >  >> RDS >> Mysql

MySQL LEFT JOIN met MAX &GROUP BY op samengevoegde tafel?

Het "laatste per groep" probleem is extreem gebruikelijk in SQL. Alleen al op deze site zijn talloze voorbeelden van oplossingen voor dit probleem te vinden.

Als uw tijdstempels uniek zijn per ledenactiviteit:

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)

als alternatief, als uw activiteits-ID in de loop van de tijd monotoon toeneemt:

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

Je hoeft niet te groeperen. Maar de zoekopdracht heeft baat bij een index op activities over (member_id, timestamp) of (member_id, id) , respectievelijk.

BEWERKEN

Om leden te laten zien die geen activiteit hebben gelogd, gebruik je een left join zoals deze.

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)

Merk op dat er geen WHERE . is clausule. Semantisch wordt WHERE toegepast na de koppelingen zijn gedaan. Dus een WHERE-clausule zou de rijen verwijderen die de LEFT JOIN heeft toegevoegd, wat in feite hetzelfde resultaat oplevert als de oorspronkelijke INNER JOIN.

Maar als u het aanvullende predikaatrecht toepast in de join-voorwaarde, werkt de LEFT JOIN zoals verwacht.



  1. Hoe de ODP.NET-verbindingspool op verbindingsfouten wissen?

  2. php-code om pdo te testen is beschikbaar?

  3. Stappen die u moet nemen als u een MySQL-storing heeft

  4. Wat is de meest elegante manier om een ​​tijdstempel met nanosec op te slaan in postgresql?