views:

56

answers:

4

I want to select the 10 last messages you received OR you sent TO different users.

For example the results must be shown like that: 

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 looks like:

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 
) 

I think Facebook (and the iPhone) uses this solution. When you go to your mail box, you have the last messages received/sent grouped by Users (friends).

So I will take an example. If I have theses messages (THEY ARE ORDERED YET):

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

Only Message with ** should be returned because they are the LAST messages I sent/received By User.

In fact I want the last message of EACH discussion.

What is the solution?

+2  A: 

The question is somewhat unclear. If you simply want the last 10 messages that involve user #12345, simply use:

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

Update to match your updated requirements. Not the most elegant, but works as long as no user sends two messages at the same second.

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
Max Shawabkeh
Your query is good but it is not really what i want. I explained you below.
Yako malin
No bad. But what about the solution I proposed below ?
Yako malin
Ok Max your query is better THAN mine. It works properly.I just used ID instead of time because it is faster to order with ID than TIME and you can send message at the same time
Yako malin
A: 

Your query is pretty good but I only get the 10 last messages I received or I sent.

But I want to GROUP them BY users/sender.

Yako malin
I'm still not entirely sure what you are looking for. Are you saying that you want the last 10 users that have received or sent a message and then for those 10 users you want the time and the type (sent/received) of the most recent message.
Steve Weet
I think this is what I want.I want the last 10 users I chatted with. And for this 10 last users I want the last message I sent or received.
Yako malin
A: 

Perhaps you're looking for GROUP BY, although having separate fields for Sender and Receiver makes it harder.

IMHO it would be better to have UserID and MessageDirection SET('IN','OUT' ).

Then you could make

SELECT UserID, MAX(time) GROUP BY UserID

Edit

If you want last 10

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

It's probably not the fastest solution and can be optimized.

Dmitry Yudakov
Yeah in fact it is not possible to group by RECEIVER and SENDER at the same time. I will try your solution. I give you a backup soon.
Yako malin
In fact I think it is not possible avoiding to have the 2 fields sender or receiver because with your solution I won't be able to know who has sent or received the message
Yako malin
You could group by `IF(receiver = 12345, sender, receiver)`.
Max Shawabkeh
Max,I used your solution by making this request : SELECT *FROM messagesWHERE receiver =6OR sender =6GROUP BY IF( receiver =6, sender, receiver )ORDER BY sendtime DESCIt returns me messages to/from differents users but not the last message like if "sendtime DESC" was ignored
Yako malin
A: 

I think I have found a solution using Max Shawabkeh tips. But in fact I think I can optimize it.

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 ) 

I think there is a better solution ....

Yako malin