PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment obtenir le dernier message dans chaque conversation d'un certain utilisateur en SQL ?

En supposant que les utilisateurs avec l'ID 1 et 3 , comme vous l'avez fait dans le violon, nous sommes intéressés par le message avec le dernier created_at et (sender_id, receiver_id) étant (1,3) ou (3,1) .

Vous pouvez utiliser des types de lignes ad hoc pour raccourcir la syntaxe :

SELECT * 
FROM   messages 
WHERE  (sender_id, receiver_id) IN ((1,3), (3,1))
ORDER  BY created_at DESC
LIMIT  1;

Ou explicitement (et légèrement plus rapide, aussi plus facile à utiliser avec les index) :

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;

Pour tous conversations d'un utilisateur

Solution ajoutée selon la demande en commentaire.

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;

L'approche ici consiste à plier l'expéditeur / le destinataire étranger dans une colonne pour simplifier l'extraction de la dernière ligne.

Explication détaillée pour DISTINCT ON dans cette réponse connexe :
Sélectionner la première ligne de chaque groupe GROUP BY ?

-> SQLfiddle mis à jour .

Considérez également le cas de test amélioré et simplifié dans le violon.