简体   繁体   中英

How to get the most recent row in group in mysql?

In my mysql query, I try to get all threads with their most recent row.

    $query = "SELECT th.id, tm.message, tm.date_sent, tm.date_sent>tu.last_read_date AS new
              FROM thread th
              JOIN thread_user tu ON th.id=tu.thread_id AND tu.user_id={$user_id}
              JOIN thread_message tm ON th.id=tm.thread_id
              JOIN (
                   SELECT thread_id, MAX(date_sent) date_sent
                   FROM thread_message
                   GROUP BY thread_id
              ) q ON tm.thread_id = q.thread_id AND tm.date_sent = q.date_sent
              ORDER BY tm.date_sent DESC";  

This works, but the problem is, if there is two or more rows who's date is the most recent and they are the same date, then it will join with both of them. I need that third join statement to join with at most 1 row.

I also don't want to assume that the biggest id implies its the most recent row, because I could always change the dates manually later.

Does anyone know how to fix this?

Thanks

One way to do this is to establish a row number per group, in this case your group is thread_id and date_sent . With MySql , you need to use user-defined variables to do this:

SELECT th.id, 
    tm.message, 
    tm.date_sent, 
    tm.date_sent>tu.last_read_date AS new
FROM thread th
    JOIN thread_user tu ON th.id=tu.thread_id AND tu.user_id={$user_id}
    JOIN (
        SELECT id,
               thread_id, 
               message, 
               date_sent, 
               @rn:=IF(@prevthread_id=thread_id, @rn+1, 1) rn,
               @prevthread_id:=thread_id
        FROM thread_message, (SELECT @rn:=1, @prevthread_id:=0) t
        ORDER BY thread_id, date_sent DESC, id
    ) tm ON th.id=tm.thread_id
           AND tm.rn = 1 
ORDER BY tm.date_sent DESC

Perhaps this is easier for you (but only because you're using mysql ):

SELECT th.id, 
    tm.message, 
    tm.date_sent, 
    tm.date_sent>tu.last_read_date AS new
FROM thread th
    JOIN thread_user tu ON th.id=tu.thread_id AND tu.user_id={$user_id}
    JOIN thread_message tm ON th.id=tm.thread_id
    JOIN (
        SELECT thread_id, 
               id, 
               MAX(date_sent) date_sent
        FROM thread_message
        GROUP BY thread_id
    ) q ON tm.thread_id = q.thread_id 
           AND q.id = tm.id 
           AND tm.date_sent = q.date_sent
ORDER BY tm.date_sent DESC

This will return an arbitrary id to join on.

Seems to me that if the query produces what you expect, with exception of the last JOIN you can just modify the GROUP BY which will only return one row.

JOIN (
      SELECT thread_id, MAX(date_sent) date_sent
      FROM thread_message
      GROUP BY thread_id
      ) q ON tm.thread_id = q.thread_id AND tm.date_sent = q.date_sent
      GROUP BY tm.date_sent
      ORDER BY tm.date_sent DESC";

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