2010-04-29 2 views
0

Je veux sélectionner les 10 derniers messages que vous avez reçus OU que vous avez envoyés à différents utilisateurs.Demande de sélectionner les 10 derniers messages envoyés/reçus à/par différents utilisateurs

Par exemple, les résultats doivent être affichés comme ça:

1. John1 - last message received 04/17/10 3:12 
2. Thomy - last message sent 04/16/10 1:26 
3. Pamela - last message received 04/12/10 3:51 
4. Freddy - last message received 03/28/10 9:00 
5. Jack - last message sent 03/20/10 4:53 
6. Tom - last message received 02/01/10 7:41 
..... 

Table ressemble:

CREATE TABLE `messages` ( 
`id` int(11) NOT NULL AUTO_INCREMENT, 
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
`sender` int(11) DEFAULT NULL, 
`receiver` int(11) DEFAULT NULL, 
`content` text 
) 

Je pense que Facebook (et l'iPhone) utilise cette solution. Lorsque vous allez dans votre boîte aux lettres, vous avez les derniers messages reçus/envoyés groupés par les utilisateurs (amis).

Je vais donc prendre un exemple. Si j'ai des messages de thèses (ILS SONT ENCORE ORDONNÉES):

**Mike** 
**Tom** 
**Pam** 
Mike 
Mike 
**John** 
John 
Pam 
**Steve** 
**Bobby** 
Steve 
Steve 
Bobby 

seul message avec **** doit être retourné, car ils sont les messages que je DERNIERS envoyés/reçus par l'utilisateur.

En fait, je veux le dernier message de CHAQUE discussion.

Quelle est la solution?

Répondre

3

La question n'est pas très claire. Si vous voulez simplement les 10 derniers messages qui impliquent l'utilisateur # 12345, utilisez simplement:

SELECT * 
FROM  messages 
WHERE sender = 12345 OR receiver = 12345 
ORDER BY time DESC 
LIMIT 10 

Mettez à jour pour répondre à vos besoins mis à jour. Pas le plus élégant, mais fonctionne aussi longtemps qu'aucun utilisateur n'envoie deux messages à la même seconde.

SELECT m1.* 
FROM  messages m1 
     INNER JOIN (SELECT MAX(time) AS time, 
           IF(receiver = 12345, sender, receiver) AS user 
        FROM  messages 
        GROUP BY user) m2 
      ON m1.time = m2.time AND (m1.sender = m2.user OR m1.receiver = m2.user) 
WHERE sender = 12345 OR receiver = 12345 
ORDER BY m1.time DESC 
+0

Votre requête est bonne, mais il est pas vraiment ce que je vouloir. Je vous ai expliqué ci-dessous. –

+0

Pas mal. Mais qu'en est-il de la solution que j'ai proposée ci-dessous? –

+0

Ok Max votre requête est meilleure que la mienne. Cela fonctionne correctement. Je viens d'utiliser ID au lieu de l'heure car il est plus rapide de commander avec ID que TIME et vous pouvez envoyer un message en même temps –

0

Peut-être que vous cherchez GROUP BY, bien qu'ayant des champs séparés pour Sender et Receiver rend plus difficile. A mon humble avis, il serait préférable d'avoir UserID et MessageDirection SET('IN','OUT').

Ensuite, vous pouvez faire

SELECT UserID, MAX(time) GROUP BY UserID 

Modifier

Si vous voulez dernier 10

SELECT UserID, MAX(time) GROUP BY UserID ORDER BY time LIMIT 10 

Il est probablement pas la solution la plus rapide et peut être optimisée.

+0

Ouais en fait il n'est pas possible de grouper par RECEIVER et SENDER en même temps. Je vais essayer votre solution. Je vous donne une sauvegarde bientôt. –

+0

En fait je pense qu'il n'est pas possible d'éviter d'avoir les 2 champs expéditeur ou destinataire car avec votre solution je ne serai pas capable de savoir qui a envoyé ou reçu le message –

+0

Vous pouvez regrouper par 'IF (récepteur = 12345, expéditeur , récepteur) –

0

Je pense avoir trouvé une solution en utilisant les conseils de Max Shawabkeh. Mais en fait je pense pouvoir l'optimiser.

SELECT * 
FROM 

(
SELECT * 
FROM messages 
ORDER BY sendtime DESC 
) messages2 

WHERE receiver = @id_user 
OR sender = @id_user 
GROUP BY IF(receiver = @id_user, sender, receiver) 

Je pense qu'il ya une meilleure solution ....

1

la requête de Max Shawabkeh m'a vraiment aidé à comprendre cette question. En l'implémentant sur un site que je suis en train de développer, j'ai trouvé une condition de contour qui a manqué.

Il existe essentiellement trois états qui sont possibles pour chaque thread de message:

  1. Vous avez envoyé des messages avant et en arrière.
  2. Vous avez seulement envoyé des messages à l'autre utilisateur.
  3. Vous avez uniquement reçu des messages de l'autre utilisateur.

("Vous" est défini en tant qu'utilisateur pour lequel vous 12345 récupérez les fils de messages.)

requête Max état manqué # 3. J'ai trouvé que l'ajout d'une clause WHERE à la requête dans le INNER JOIN non seulement fixe, il limite aussi les résultats que les discussions relatives à l'utilisateur 12345.

SELECT m1.* 
FROM  messages m1 
     INNER JOIN (SELECT MAX(time) AS time, 
           IF(receiver = 12345, sender, receiver) AS user 
        FROM  messages 
        WHERE sender_id = 12345 OR receiver_id = 12345 
        GROUP BY user) m2 
      ON m1.time = m2.time AND (m1.sender = m2.user OR m1.receiver = m2.user) 
WHERE sender = 12345 OR receiver = 12345 
ORDER BY m1.time DESC 
Questions connexes