Problemet skyldes en MySQL-specifik udvidelse til adfærden for GROUP BY
klausul. Andre databaser ville give en fejl... noget, der ligner on-aggregation i SELECT-listen". (Vi kan få MySQL til at kaste en lignende fejl, hvis vi inkluderer ONLY_FULL_GROUP_BY i sql_mode.)
Problemet med udtrykket messages.created
er, der refererer til en værdi fra en ubestemt række i GROUP BY. ORDER BY operationen sker meget senere i behandlingen, efter GROUP BY operationen.
For at få det "seneste" oprettet for hver gruppe, skal du bruge et aggregat udtryk MAX(messages.created)
.
At få de andre værdier fra den samme række er lidt mere kompliceret.
Forudsat at created
er unik inden for en given conversation_id
gruppe (eller, hvis der ikke er garanti for, at den ikke er unik, og du er okay med at returnere flere rækker med samme værdi for created
...
For at få den seneste created
for hver 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 bruge det som en indlejret visning for at få hele rækken med den seneste 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)
BEMÆRKNINGER:
Du kan tilføje en ORDER BY
klausul for at bestille rækkerne returneret, som du har brug for.
WHERE
klausul på den ydre forespørgsel er sandsynligvis overflødig og unødvendig.
Vi foretrækker at undgå at bruge SELECT *
, og foretrækker eksplicit at angive de udtryk, der skal returneres.