Problem wynika z specyficznego dla MySQL rozszerzenia zachowania GROUP BY
klauzula. Inne bazy danych wygenerują błąd... coś podobnego do on-aggregate na liście SELECT”. (Możemy sprawić, by MySQL rzucił podobny błąd, jeśli włączymy ONLY_FULL_GROUP_BY w sql_mode.)
Problem z wyrażeniem messages.created
oznacza, że odnosi się do wartości z nieokreślonego wiersza w grupie GROUP BY. Operacja ORDER BY występuje znacznie później w przetwarzaniu, po operacji GROUP BY.
Aby uzyskać „najnowsze” utworzone dla każdej grupy, użyj agregatu wyrażenie MAX(messages.created)
.
Pobranie innych wartości z tego samego wiersza jest nieco bardziej skomplikowane.
Zakładając, że created
jest wyjątkowy w ramach danego conversation_id
grupa (lub, jeśli nie ma gwarancji, że nie jest unikalna i możesz zwrócić wiele wierszy o tej samej wartości dla created
...
Aby uzyskać najnowsze created
dla każdego 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
Możesz użyć tego jako widoku wbudowanego, aby uzyskać cały wiersz z ostatnim 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)
UWAGI:
Możesz dodać ORDER BY
klauzula, aby uporządkować zwracane wiersze w dowolny sposób.
WHERE
klauzula w zewnętrznym zapytaniu jest prawdopodobnie zbędna i niepotrzebna.
Wolimy unikać używania SELECT *
i wolą jawnie wyszczególnić wyrażenia, które mają zostać zwrócone.