Het probleem is te wijten aan een MySQL-specifieke uitbreiding van het gedrag van de GROUP BY
clausule. Andere databases zouden een fout geven... iets dat lijkt op on-aggregate in SELECT list". (We kunnen MySQL een soortgelijke fout laten genereren, als we ONLY_FULL_GROUP_BY opnemen in sql_mode.)
Het probleem met de uitdrukking messages.created
is dat verwijst naar een waarde uit een onbepaalde rij in de GROUP BY. De ORDER BY-bewerking vindt veel later in de verwerking plaats, na de GROUP BY-bewerking.
Gebruik een aggregaat . om het "nieuwste" voor elke groep te krijgen uitdrukking MAX(messages.created)
.
Het is iets ingewikkelder om de andere waarden uit dezelfde rij te halen.
Ervan uitgaande dat created
is uniek binnen een gegeven conversation_id
groep (of, als er geen garantie is dat het niet uniek is, en je bent akkoord met het retourneren van meerdere rijen met dezelfde waarde voor created
...
Om de nieuwste created
te krijgen voor elke 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
Je kunt dat gebruiken als een inline-weergave om de hele rij te krijgen met die laatste 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)
OPMERKINGEN:
U kunt een ORDER BY
. toevoegen clausule om de geretourneerde rijen te ordenen zoals u dat wilt.
De WHERE
clausule op de buitenste query is waarschijnlijk overbodig en onnodig.
We vermijden liever het gebruik van SELECT *
, en geven er de voorkeur aan expliciet de expressies te vermelden die moeten worden geretourneerd.