Problemet beror på en MySQL-specifik förlängning av beteendet hos GROUP BY
klausul. Andra databaser skulle skapa ett fel... något som liknar on-aggregate i SELECT-listan". (Vi kan få MySQL att skicka ett liknande fel, om vi inkluderar ONLY_FULL_GROUP_BY i sql_mode.)
Problemet med uttrycket messages.created
är som refererar till ett värde från en obestämd rad i GROUP BY. ORDER BY operationen inträffar mycket senare i behandlingen, efter GROUP BY operationen.
För att få det "senaste" skapat för varje grupp, använd ett aggregat uttryck MAX(messages.created)
.
Att få de andra värdena från samma rad är lite mer komplicerat.
Förutsatt att created
är unikt inom ett givet conversation_id
grupp (eller, om det inte är garanterat att det inte är unikt, och du är okej med att returnera flera rader med samma värde för created
...
För att få den senaste created
för varje 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
Du kan använda det som en inlinevy för att få hela raden med den senast 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)
ANMÄRKNINGAR:
Du kan lägga till en ORDER BY
klausul för att beställa raderna som returneras hur du behöver.
WHERE
klausulen på den yttre frågan är sannolikt överflödig och onödig.
Vi föredrar att undvika att använda SELECT *
, och föredrar att uttryckligen lista de uttryck som ska returneras.