简体   繁体   中英

Group by only showing the first record

I'm trying to grab some conversation records in my database however only show the latest result. I've tried the below however it groups by the first record found is there a way I can make it group by the last record on the dateline colum

  SELECT DISTINCT*
  FROM table_messages 
  WHERE fromid=4 OR toid=4
  GROUP BY convoid
  ORDER BY dateline desc

My table is like the below

pmid - fromid - toid - convoid - dateline
 1       4        15      3      1461079193
 2       4        15      3      1461079200
 3       15        4      3      1461079220
 4       15        4      3      1461079230
 5       4        15      3      1461079270

To get a list of all the conversations for a specific user, and the last message sent (and it's details) for each conversation, in a single query:

SELECT
    convo.convoid,
    message.pmid,
    message.dateline,
    CASE WHEN fromid = 4 then "SENT" ELSE "RECEIVED" as direction
FROM
    (SELECT convoid, max(dateline) as maxdateline FROM table_messages GROUP BY convoid) convo
    INNER JOIN table_messages message
        ON convo.convoid = message.convoid AND
            convo.maxdateline = message.dateline
WHERE 
    fromid = 4 or toid = 4

Here we are working with two sets again. The first (from the FROM ) is a list of all convoid's and their max dateline . Then we INNER JOIN those with the same table on the relationship of convoid and dateline. This will give us a record set of every conversation and it's most recent message.

Then we restrict in the WHERE clause to get just the conversations where either the fromid or the toid is the user you are interested in.

For the fun, I added the CASE statement, just to bring in more information about that last message sent (whether it was sent by the user or received by the user).


It MIGHT be quicker to do:

SELECT
    convo.convoid,
    message.pmid,
    message.dateline,
    CASE WHEN fromid = 4 then "SENT" ELSE "RECEIVED" as direction
FROM
    (SELECT convoid, max(dateline) as maxdateline FROM table_messages GROUP BY convoid WHERE fromid = 4 or toid = 4) convo
    INNER JOIN table_messages message
        ON convo.convoid = message.convoid AND
            convo.maxdateline = message.dateline

Depending on how MySQL optimizes the first query. If it tries to get every conversation and then the last message, then restricts it for the user then you can force the optimizer to instead, with this version, only get conversations for the user, then get the latest message for those conversations. My bet though is that it's a wash and that MySQL will properly optimize the first query to do what is explicitly stated in the second. But... I figured just in case, I would put it here.

For readability sake, I like the first query better since one can very quickly see the conditions in the main query's WHERE clause. Otherwise you have to hunt in the subquery.

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