skip to Main Content

I need to get the latest row of each combinations of sender_id & receiver_id

my messaging table:

CREATE TABLE messaging (
  msg_id SERIAL,
  sender_id BIGINT  NOT NULL ,
  receiver_id varchar(255) NOT NULL ,
  msg text default NULL,
  media_link TEXT DEFAULT NULL,
  sent_time TIMESTAMP NOT NULL DEFAULT NOW(),
  received_time TIMESTAMP default NULL,
  msg_type ENUM('text','link','file') default 'text',
  is_seen BINARY DEFAULT 0
  ) ENGINE=InnoDB;

Sample data:

+------+---------+-----------+---------------+----------+-------------------+-------------+--------+-------+
|msg_id|sender_id|receiver_id|msg            |media_link|sent_time          |received_time|msg_type|is_seen|
+------+---------+-----------+---------------+----------+-------------------+-------------+--------+-------+
|1     |1        |10         |hi             |NULL      |2022-11-08 19:11:53|NULL         |text    |0      |
|2     |1        |10         |r u there?     |NULL      |2022-11-08 19:12:46|NULL         |text    |0      |
|3     |7        |10         |hi             |NULL      |2022-11-08 19:13:13|NULL         |text    |0      |
|4     |7        |10         |where r u from?|NULL      |2022-11-08 20:31:17|NULL         |text    |0      |
+------+---------+-----------+---------------+----------+-------------------+-------------+--------+-------+

ORDER BY latest with each sender_id receiver_id combination the result should look like this:

+------+---------+-----------+---------------+----------+-------------------+-------------+--------+-------+
|msg_id|sender_id|receiver_id|msg            |media_link|sent_time          |received_time|msg_type|is_seen|
+------+---------+-----------+---------------+----------+-------------------+-------------+--------+-------+
|2     |1        |10         |r u there?     |NULL      |2022-11-08 19:12:46|NULL         |text    |0      |
|4     |7        |10         |where r u from?|NULL      |2022-11-08 20:31:17|NULL         |text    |0      |
+------+---------+-----------+---------------+----------+-------------------+-------------+--------+-------+

I have tried this statement:

SELECT msg_id, 
       sender_id, 
       receiver_id, 
       msg, 
       media_link, 
       sent_time, 
       received_time, 
       msg_type, 
       is_seen  
FROM messaging  
WHERE sender_id = 10 OR receiver_id = 10 
GROUP BY sender_id,receiver_id  
ORDER BY msg_id DESC;

which gives there rows ascending order of each group:

+------+---------+-----------+---+----------+-------------------+-------------+--------+-------+
|msg_id|sender_id|receiver_id|msg|media_link|sent_time          |received_time|msg_type|is_seen|
+------+---------+-----------+---+----------+-------------------+-------------+--------+-------+
|3     |7        |10         |hi |NULL      |2022-11-08 19:13:13|NULL         |text    |0      |
|1     |1        |10         |hi |NULL      |2022-11-08 19:11:53|NULL         |text    |0      |
+------+---------+-----------+---+----------+-------------------+-------------+--------+-------+

But it is only showing oldest row of each group by combination.

I am still learning Mysql. Please help me

2

Answers


    • if you need a recent row, then there must be a specific timeframe field that you are looking at i.e sent_time
    • you can use that timeframe field in the ORDER BY by clause of the row_number() function to create a rank. This rank would give a value of 1 for the most recent timeframe field with the combination of sennder and receiver id (see partition by caluse )
    • Lastly you can filter on rank_ = 1
    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
    
    Login or Signup to reply.
  1. You do not need to specify NULL when setting default value in TIMESTAMP, it will return an error.
    Do it instead:

    CREATE TABLE messaging (
      msg_id SERIAL,
      sender_id BIGINT  NOT NULL ,
      receiver_id varchar(255) 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;
    
        insert into messaging 
    VALUES(  NULL,   123,  'ABC',  'THIS IS A TEXT',  DEFAULT,  DEFAULT,  NULL,  'text',  DEFAULT),
    (  NULL,   456,  'DFG',  'TEXT THIS IS',  DEFAULT,  DEFAULT,  NULL,  'link',  DEFAULT),
    (  NULL,   789,  'HIJ',  'MAY THE FORCE BE WITH',  DEFAULT,  DEFAULT,  NULL,  'link',  DEFAULT),
    (  NULL,   456,  'KLM',  'YOU',  DEFAULT,  DEFAULT,  NULL,  'link',  DEFAULT);
    

    I’ve found two ways to acheive to your need:

    # UNION WAY
    SELECT * FROM(
    SELECT MAX(t.sender_id), 'sender_id' as type
    FROM messaging t
    union all
    SELECT MAX(t2.receiver_id), 'receiver_id' as type
    FROM messaging t2) t3;
    
    # SUBSELECT WAY
    SELECT MAX(sender_id) AS MAX_sender_id,
      (SELECT MAX(t2.receiver_id)
       FROM messaging t2) AS MAX_receiver_id 
    FROM messaging t;
    

    Check the result here -> SQL Fiddle

    Let me know if it helped

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search