简体   繁体   中英

Returning last record in a subquery - MySQL

So I am creating a messaging system similar to Facebook's style for my website (I know right). What I intend to happen is list all conversations for the user and also return the last message in the conversation. Problem is I am getting the first message when doing a GROUP BY. Perhaps I am going about it in the wrong way.

The structure of the database consists of three tables. conversations , conversations_assign , conversations_msg

conversations just stores the outside data of the conversation and the important thing is the id

conversations_assign does just that. It lists the userid of everyone in the conversation

conversations_msg stores obviously the message, user who posted with other data.

Everything is tied together with conversations.id = conv_id

Here is the query I have and as I said from above with GROUP BY it is returning the first result. Taking off GROUP BY and adding LIMIT 1 literally returns one message and the rest are null. Any help is appreciated, thanks!

SELECT conversations.id,
    conversations_assign.num_unread,
    message
FROM conversations_assign
INNER JOIN conversations ON conversations_assign.conv_id=conversations.id                                     
LEFT JOIN (
    SELECT conv_id, message, msg_time
    FROM conversations_msg
    GROUP BY conv_id
) AS message ON message.conv_id=conversations_assign.conv_id
WHERE conversations_assign.userid='XXsomeidXX'
ORDER BY message.msg_time DESC

You can't do what you want with aggregation. Instead, you need to filter . If you are running MySQL 8.0, I would recommend window functions:

select c.id, ca.num_unread, cm.message
from conversations_assign c
inner join conversations ca on ca.conv_id =c.id                                     
left join (
    select cm.*, rank() over(partition by conv_id order by msg_time desc) rn
    from conversations_msg cm
) as cm on cm.conv_id = ca.conv_id and cm.rn = 1
where ca.userid = 'xxsomeidxx'
order by cm.msg_time desc

In earlier versions, an alternative uses a correlated subquery to filter the left join :

select c.id, ca.num_unread, cm.message
from conversations_assign c
inner join conversations ca 
    on  ca.conv_id =c.id                                     
left join conversations_msg cm
    on  cm.conv_id = ca.conv_id 
    and cm.msg_time = (
        select max(cm1.msg_time) from conversations_msg cm1 where cm1.conv_id = ca.conv_id
    )
where ca.userid = 'xxsomeidxx'
order by cm.msg_time 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