El problema se debe a una extensión específica de MySQL para el comportamiento de GROUP BY
cláusula. Otras bases de datos generarían un error... algo similar a agregado en la lista SELECT". (Podemos hacer que MySQL arroje un error similar, si incluimos ONLY_FULL_GROUP_BY en sql_mode).
El problema con la expresión messages.created
es que hace referencia a un valor de una fila indeterminada en el GROUP BY. La operación ORDER BY ocurre mucho más tarde en el procesamiento, después de la operación GROUP BY.
Para obtener el "último" creado para cada grupo, use un agregado expresión MAX(messages.created)
.
Obtener los demás valores de esa misma fila es un poco más complicado.
Suponiendo que created
es único dentro de un conversation_id
dado grupo (o, si no hay garantía de que no sea único, y está de acuerdo con devolver varias filas con el mismo valor para created
...
Para obtener el último created
para cada 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
Puede usar eso como una vista en línea, para obtener la fila completa con el último 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)
NOTAS:
Puedes agregar un ORDER BY
cláusula para ordenar las filas devueltas como necesites.
El WHERE
La cláusula sobre la consulta externa probablemente sea redundante e innecesaria.
Preferimos evitar usar SELECT *
y prefieren enumerar explícitamente las expresiones que se devolverán.