Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Sortieren Sie die Auswahl basierend auf den Beitrittsergebnissen (Sortieren Sie Konversationen nach der zuletzt gesendeten Nachricht)

Das Problem ist auf eine MySQL-spezifische Erweiterung des Verhaltens von GROUP BY zurückzuführen Klausel. Andere Datenbanken würden einen Fehler ausgeben ... so etwas wie On-Aggregate in der SELECT-Liste". (Wir können MySQL dazu bringen, einen ähnlichen Fehler auszugeben, wenn wir ONLY_FULL_GROUP_BY in sql_mode einbeziehen.)

Das Problem mit dem Ausdruck messages.created bezieht sich auf einen Wert aus einer unbestimmten Zeile in GROUP BY. Die ORDER BY-Operation erfolgt viel später in der Verarbeitung, nach der GROUP BY-Operation.

Verwenden Sie ein Aggregat, um das "Neueste" für jede Gruppe erstellt zu bekommen Ausdruck MAX(messages.created) .

Die anderen Werte aus derselben Zeile zu erhalten, ist etwas komplizierter.

Angenommen, dass created ist einzigartig innerhalb einer bestimmten conversation_id group (oder, wenn es nicht garantiert ist, dass es nicht eindeutig ist, und Sie damit einverstanden sind, mehrere Zeilen mit demselben Wert für created zurückzugeben ...

Um den neusten created zu erhalten für jede conversation_id

SELECT lm.conversation_id
     , MAX(lm.created) AS created
  FROM conversation lc
  JOIN message lm
    ON lm.conversation_id = lc.id
 WHERE (lc.creator_id = :userId OR lc.to_id = :userId)
 GROUP BY lm.conversation_id

Sie können dies als Inline-Ansicht verwenden, um die gesamte Zeile mit diesem zuletzt created zu erhalten

SELECT c.*
     , m.*
  FROM ( SELECT lm.conversation_id
              , MAX(lm.created) AS created
           FROM conversation lc
           JOIN message lm
             ON lm.conversation_id = lc.id
          WHERE (lc.creator_id = :userId OR lc.to_id = :userId)
          GROUP BY lm.conversation_id
       ) l
  JOIN conversation c
    ON c.id = l.conversation_id
  JOIN messages m
    ON m.conversation_id = l.conversation_id
   AND m.created         = l.created
 WHERE (c.creator_id = :userId OR c.to_id = :userId)

HINWEISE:

Sie können einen ORDER BY hinzufügen -Klausel, um die zurückgegebenen Zeilen nach Bedarf anzuordnen.

Das WHERE -Klausel in der äußeren Abfrage ist wahrscheinlich redundant und unnötig.

Wir ziehen es vor, SELECT * zu vermeiden , und ziehen es vor, die zurückzugebenden Ausdrücke explizit aufzulisten.