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.