Assumindo os usuários com ID
1
e 3
, como você fez no violino, estamos interessados na mensagem com a última created_at
e (sender_id, receiver_id)
sendo (1,3)
ou (3,1)
. Você pode usar tipos de linha ad hoc para tornar a sintaxe curta:
SELECT *
FROM messages
WHERE (sender_id, receiver_id) IN ((1,3), (3,1))
ORDER BY created_at DESC
LIMIT 1;
Ou explicitamente (e um pouco mais rápido, também mais fácil de usar com índices):
SELECT *
FROM messages
WHERE (sender_id = 1 AND receiver_id = 3 OR
sender_id = 3 AND receiver_id = 1)
ORDER BY created_at DESC
LIMIT 1;
Para todos conversas de um usuário
Solução adicionada conforme solicitação no comentário.
SELECT DISTINCT ON (user_id) *
FROM (
SELECT 'out' AS type, id, receiver_id AS user_id, body, created_at
FROM messages
WHERE sender_id = 1
UNION ALL
SELECT 'in' AS type, id, sender_id AS user_id, body, created_at
FROM messages
WHERE receiver_id = 1
) sub
ORDER BY user_id, created_at DESC;
A abordagem aqui é dobrar o remetente/receptor estrangeiro em uma coluna para simplificar a extração da última linha.
Explicação detalhada para
DISTINCT ON
nesta resposta relacionada:Selecionar a primeira linha em cada grupo GROUP BY?
-> SQLfiddle atualizado .
Considere também o caso de teste aprimorado e simplificado no violino.