Проблемът се дължи на специфично за MySQL разширение за поведението на GROUP BY
клауза. Други бази данни биха извадили грешка... нещо подобно на on-agregate в списъка SELECT". (Можем да накараме MySQL да изведе подобна грешка, ако включим ONLY_FULL_GROUP_BY в sql_mode.)
Проблемът с израза messages.created
е, че се отнася до стойност от неопределен ред в GROUP BY. Операцията ORDER BY се появява много по-късно при обработката, след операцията GROUP BY.
За да получите „най-новото“, създадено за всяка група, използвайте агрегат израз MAX(messages.created)
.
За да получите другите стойности от същия ред, е малко по-сложно.
Ако приемем, че created
е уникален в рамките на даден conversation_id
група (или, ако няма гаранция, че не е уникална и сте добре да връщате няколко реда с една и съща стойност за created
...
За да получите най-новото created
за всеки 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
Можете да го използвате като вграден изглед, за да получите целия ред с този най-нов 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)
БЕЛЕЖКИ:
Можете да добавите ORDER BY
клауза, за да подредите връщането на редовете, колкото ви е необходимо.
WHERE
клаузата във външната заявка вероятно е излишна и ненужна.
Предпочитаме да избягваме използването на SELECT *
и предпочитат изрично да изброят изразите, които трябва да бъдат върнати.