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

Ordine Seleziona in base ai risultati dell'unione (ordina le conversazioni in base all'ultimo messaggio inviato)

Il problema è dovuto a un'estensione specifica di MySQL al comportamento di GROUP BY clausola. Altri database genererebbero un errore... qualcosa di simile a on-aggregate nell'elenco SELECT". (Possiamo fare in modo che MySQL generi un errore simile, se includiamo ONLY_FULL_GROUP_BY in sql_mode.)

Il problema con l'espressione messages.created è che si riferisce a un valore da una riga indeterminata nel GROUP BY. L'operazione ORDER BY avviene molto più avanti nell'elaborazione, dopo l'operazione GROUP BY.

Per ottenere le "ultime" create per ogni gruppo, utilizza un aggregato espressione MAX(messages.created) .

Ottenere gli altri valori dalla stessa riga è un po' più complicato.

Supponendo che created è unico all'interno di un dato conversation_id gruppo (o, se non è garantito che non sia univoco e sei d'accordo a restituire più righe con lo stesso valore per created ...

Per ottenere l'ultimo created per ogni 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

Puoi usarlo come vista in linea, per ottenere l'intera riga con l'ultimo created

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)

NOTE:

Puoi aggiungere un ORDER BY clausola per ordinare le righe restituite come preferisci.

Il WHERE La clausola sulla query esterna è probabilmente ridondante e non necessaria.

Preferiamo evitare di utilizzare SELECT * e preferisce elencare in modo esplicito le espressioni da restituire.