Reputation: 13
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
Upvotes: 0
Views: 136
Reputation: 222472
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
Upvotes: 1