I am using mysql 8.0.23
I have three tables, chats
, chat_users
and chat_messages
I want to select the chat_id, the last message (with maximum createdAt date for a particular group. Said in other words, the message order by created_at desc within the group), from_user_id values for all the chats where user with id 1 is a member.
The tables sql and DDLs is are like below
create table chats
(
id int unsigned auto_increment primary key,
created_at timestamp default CURRENT_TIMESTAMP not null
);
create table if not exists chat_users
(
id int unsigned auto_increment
primary key,
chat_id int unsigned not null,
user_id int unsigned not null,
constraint chat_users_user_id_chat_id_unique
unique (user_id, chat_id),
constraint chat_users_chat_id_foreign
foreign key (chat_id) references chats (id)
);
create index chat_users_chat_id_index
on chat_users (chat_id);
create index chat_users_user_id_index
on chat_users (user_id);
create table chat_messages
(
id int unsigned auto_increment primary key,
chat_id int unsigned not null,
from_user_id int unsigned not null,
content varchar(500) collate utf8mb4_unicode_ci not null,
created_at timestamp default CURRENT_TIMESTAMP not null constraint chat_messages_chat_id_foreign
foreign key (chat_id) references chats (id),
);
create index chat_messages_chat_id_index
on chat_messages (chat_id);
create index chat_messages_from_user_id_index
on chat_messages (from_user_id);
The query that I tried so far and is not working properly is
SET @userId = 1;
select
c.id as chat_id,
content,
chm.from_user_id
from chat_users
inner join chats c on chat_users.chat_id = c.id
inner join chat_messages chm on c.id = chm.chat_id
where chat_users.user_id = @userId
group by c.id
order by c.id desc, max(chm.created_at) desc
My query above does not return the content
field from the last created message, although I am trying to order by max(chm.created_at) desc. This order by after group by clause is executed after the grouping I think and not within the items from the group..
I know that I can probably select in the select statement the max date but I want to select last content value within the group not select max(ch.created_at) as last_created_at_msg_within_group
I don't know how to select the content
field from the item that has the highest chm.created_at from within the group that I do by grouping with c.id
Example test data
chats
1 2021-07-23 20:51:01
2 2021-07-23 20:51:01
3 2021-07-23 20:51:01
chats_users
1 1 1
2 1 2
3 2 1
4 2 2
5 3 1
6 3 2
chat_messages
1 1 1 lastmsg 2021-07-28 21:50:31
1 1 2 themsg 2021-07-23 20:51:01
The logic in this case should return
chat_id content from_user_id
1 lastmsg 1
PS: Before posting here I did my homework and studied similar questions in the forum, but they were trying to get last inserted row from a group and were not like mine.
Here's what I came up with, for a solution for MySQL 8.0 with window functions:
select * from (
select
c.id as chat_id,
content,
chm.from_user_id,
chm.created_at,
row_number() over (partition by c.id order by chm.created_at desc) as rownum
from chat_users
inner join chats c on chat_users.chat_id = c.id
inner join chat_messages chm on c.id = chm.chat_id
where chat_users.user_id = @userId
) as t
where rownum = 1;