简体   繁体   中英

Query returns additional rows

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

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.

You are getting the last message from each user because you have done GROUP BY for both: to_user and from_user.

There is no need to use GROUP BY clause in your query.

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.

Remove the group by clause in your in statement--it's useless in this case. It's returning a sent timestamp for each distinct pairing of to_user and from_user . You really just want the max sent where to_user or from_user equal some value. Lose the group by , and you'll return exactly one record showing the latest message either to or from a user.

It looks like this:

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
   )
LIMIT 0 , 30

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM