Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Seleção de pedido com base nos resultados de junção (classificar conversas na última mensagem enviada)


O problema é devido a uma extensão específica do MySQL para o comportamento do GROUP BY cláusula. Outros bancos de dados lançariam um erro... algo parecido com on-aggregate na lista SELECT". (Podemos fazer o MySQL lançar um erro semelhante, se incluirmos ONLY_FULL_GROUP_BY em sql_mode.)

O problema com a expressão messages.created é que se refere a um valor de uma linha indeterminada no GROUP BY. A operação ORDER BY ocorre muito mais tarde no processamento, após a operação GROUP BY.

Para obter o "último" criado para cada grupo, use um agregado expressão MAX(messages.created) .

Para obter os outros valores dessa mesma linha, é um pouco mais complicado.

Supondo que created é único dentro de um determinado conversation_id group (ou, se não houver garantia de que não é exclusivo, e você não tem problema em retornar várias linhas com o mesmo valor para created ...

Para obter o ú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

Você pode usar isso como uma visualização inline, para obter a linha inteira com o ú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:

Você pode adicionar um ORDER BY cláusula para ordenar as linhas retornadas da maneira que você precisar.

O WHERE cláusula na consulta externa é provavelmente redundante e desnecessária.

Preferimos evitar o uso de SELECT * , e prefira listar explicitamente as expressões a serem retornadas.