Suponiendo que los usuarios con ID 1
y 3
, como hiciste en el violín, estamos interesados en el mensaje con el último created_at
y (sender_id, receiver_id)
siendo (1,3)
o (3,1)
.
Puede usar tipos de fila ad-hoc para acortar la sintaxis:
SELECT *
FROM messages
WHERE (sender_id, receiver_id) IN ((1,3), (3,1))
ORDER BY created_at DESC
LIMIT 1;
O explícitamente (y un poco más rápido, también más fácil de usar con í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 conversaciones de un usuario
Se agregó una solución según la solicitud en el comentario.
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;
El enfoque aquí es doblar remitente/receptor extranjero en una columna para simplificar la extracción de la última fila.
Explicación detallada de DISTINCT ON
en esta respuesta relacionada:
¿Seleccionar la primera fila en cada grupo GROUP BY?
Considere también el caso de prueba mejorado y simplificado en el violín.