Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Query returns additional rows

Tags:

sql

mysql

I have this kind of table for simple chat:

messages table structure
+----+---------+-----------+---------+------+------+
| id | to_user | from_user | message | read | sent |
+----+---------+-----------+---------+------+------+

And i need to get list of each conversation which looks like that

Username ----  Message ---- Date

I am using this query to do it:

SELECT *
FROM `messages`
WHERE `sent`
IN (
   SELECT MAX( `sent` )
   FROM `messages`
   WHERE `from_user` = '1' --id of user who is requesting the list
   OR `to_user` = '1'  --id of user who is requesting the list
   GROUP BY `to_user` , `from_user`
   )
LIMIT 0 , 30

And this works almost fine, my problem is that it returns me not the last message of that conversation but last message from each user so let's say user 1 and 2 is talking and i'm getting this list, this is what i get:

+----+---------+-----------+-----------------------+------+---------------------+
| id | to_user | from_user | message               | read | sent                |
+----+---------+-----------+-----------------------+------+---------------------+
|  3 |       2 |         1 | Message 1 from user 1 |    0 | 2012-01-11 13:20:54 |
|  4 |       1 |         2 | Message 1 from user 2 |    0 | 2012-01-11 13:24:59 |
+----+---------+-----------+-----------------------+------+---------------------+

And i would like to get only last message which is 4, cause sent field is the highest in 4th record so how can i solve it?

EDIT After deleting group by i'm getting only one message even if user was talking with more than one user

like image 467
Linas Avatar asked Jul 21 '26 17:07

Linas


2 Answers

Here's how you do it:

SELECT *
FROM (SELECT * 
  FROM messages
  WHERE from_user = ?
  OR to_user = ?
  ORDER by from_user, to_user, sent DESC
) x
GROUP BY from_user, to_user
ORDER BY sent DESC
LIMIT 1;

In mysql, a group by without aggregating the other columns returns the first row for each group. By selecting form an ordered row set (the inner query) we get the most recent row for each conversation.

like image 134
Bohemian Avatar answered Jul 23 '26 08:07

Bohemian


SELECT *
FROM `messages`
WHERE `sent`
IN (
   SELECT MAX( `sent` )
   FROM `messages`
   WHERE (`from_user` = '1' OR `to_user` = '1')
   )
LIMIT 0 , 30

the groupby is going to conbine them i believe.

like image 40
Silvertiger Avatar answered Jul 23 '26 08:07

Silvertiger