sql >> Base de Datos >  >> RDS >> Mysql

Selección de pedidos basada en los resultados de unión (Ordenar conversaciones según el último mensaje enviado)

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.