Reputation: 163
My messaging
table is:
CREATE TABLE messaging (
msg_id SERIAL,
sender_id BIGINT NOT NULL ,
receiver_id BIGINT NOT NULL ,
msg text default NULL,
media_link TEXT DEFAULT NULL,
sent_time TIMESTAMP NOT NULL DEFAULT NOW(),
received_time TIMESTAMP NULL,
msg_type ENUM('text','link','file') default 'text',
is_seen BINARY DEFAULT 0
) ENGINE=InnoDB;
Data of the table are:
+------+---------+-----------+------------------+----------+-------------------+-------------+--------+-------+
|msg_id|sender_id|receiver_id|msg |media_link|sent_time |received_time|msg_type|is_seen|
+------+---------+-----------+------------------+----------+-------------------+-------------+--------+-------+
|3 |1 |10 |hi | |2022-11-08 19:11:53|NULL |text |0 |
|4 |1 |10 |r u there? | |2022-11-08 19:12:46|NULL |text |0 |
|5 |7 |10 |hi |NULL |2022-11-09 14:11:41|NULL |text |0 |
|6 |7 |10 |where r u from? |NULL |2022-11-09 14:11:41|NULL |text |0 |
|7 |10 |1 |new here |NULL |2022-11-09 14:13:46|NULL |text |0 |
|8 |1 |7 |nice messaging app|NULL |2022-11-09 14:14:17|NULL |text |0 |
|9 |7 |1 |kind of |NULL |2022-11-09 14:14:37|NULL |text |0 |
+------+---------+-----------+------------------+----------+-------------------+-------------+--------+-------+
I tried this statement:
with main as (
select
*,
row_number() over(partition by sender_id, receiver_id order by sent_time desc) as rank_
from messaging
)
select * from main where rank_ = 1
However, it gives just every combination of receiver_id and sender_id latest message:
+------+---------+-----------+------------------+----------+-------------------+-------------+--------+-------+-----+
|msg_id|sender_id|receiver_id|msg |media_link|sent_time |received_time|msg_type|is_seen|rank_|
+------+---------+-----------+------------------+----------+-------------------+-------------+--------+-------+-----+
|8 |1 |7 |nise messeging app|NULL |2022-11-09 14:14:17|NULL |text |0 |1 |
|4 |1 |10 |r u there? | |2022-11-08 19:12:46|NULL |text |0 |1 |
|9 |7 |1 |kind of |NULL |2022-11-09 14:14:37|NULL |text |0 |1 |
|5 |7 |10 |hi |NULL |2022-11-09 14:11:41|NULL |text |0 |1 |
|7 |10 |1 |new here |NULL |2022-11-09 14:13:46|NULL |text |0 |1 |
+------+---------+-----------+------------------+----------+-------------------+-------------+--------+-------+-----+
What I need is to get sender_id and receiver_id unique constant what you use in creating unique columns, that means what we see in any messaging app: last message between unique users, like:
+------+---------+-----------+-------+----------+-------------------+-------------+--------+-------+-----+
|msg_id|sender_id|receiver_id|msg |media_link|sent_time |received_time|msg_type|is_seen|rank_|
+------+---------+-----------+-------+----------+-------------------+-------------+--------+-------+-----+
|9 |7 |1 |kind of|NULL |2022-11-09 14:14:37|NULL |text |0 |1 |
+------+---------+-----------+-------+----------+-------------------+-------------+--------+-------+-----+
|7 |10 |1 |new here|NULL |2022-11-09 14:13:46|NULL |text |0 |1 |
+------+---------+-----------+--------+----------+-------------------+-------------+--------+-------+-----+
Upvotes: 2
Views: 48
Reputation: 222482
Your query gives you the latest message per sender/receiver tuple. I understand that you want the latest message per pair of users, regardless of which of the two sends or receive.
If so, you can just tweak the partition
of row_number()
in your existing query:
with main as (
select m.*,
row_number() over(
partition by least(sender_id, receiver_id), greatest(sender_id, receiver_id)
order by sent_time desc
) as rn
from messaging
)
select * from main where rn = 1
The lest
/greaterst
expression generates a "stable" set of user tuples, where the user with the lowest id consistently comes first in the partition.
Upvotes: 1