Private messaging system. Listing last message of each conversation

前端 未结 3 1420
梦如初夏
梦如初夏 2021-02-15 17:58

Lets say this is the database structure:

\"enter

SELECT * FROM `pms` where         


        
相关标签:
3条回答
  • 2021-02-15 18:45
    select pms.* from pms 
    inner join 
        (select max(fecha) as max_fecha,
               if(id_to<id_from,id_to,id_from) min_id, 
               if(id_to<id_from,id_from,id_to) max_id
          from pms where id_to = 1 or id_from = 1 
             group by if(id_to<id_from,id_to,id_from),if(id_to<id_from,id_from,id_to)) t 
         on (if(pms.id_to<pms.id_from,pms.id_to,pms.id_from)=t.min_id) 
            and (if(pms.id_to<pms.id_from,pms.id_from,pms.id_to)=t.max_id) 
            and (pms.fecha=t.max_fecha)
    

    Also if id_to and id_from in your table are small enough to prevent overflow in statement (id_to+id_from) here is the simple query:

    select pms.* from pms 
    inner join 
        (select max(fecha) as max_fecha, id_to+id_from as sum_id
          from pms where id_to = 1 or id_from = 1 
             group by id_to+id_from) t 
         on ((pms.id_to+pms.id_from)=t.sum_id) 
            and (pms.fecha=t.max_fecha)
     where pms.id_to = 1 or pms.id_from = 1
    
    0 讨论(0)
  • 2021-02-15 18:50

    This assumes id is an auto-increment column:

    SELECT MAX(id) AS id
    FROM pms
    WHERE id_to = 1 OR id_from = 1
    GROUP BY (IF(id_to = 1, id_from, id_to))
    

    Assuming you have id_from and id_to indexed, this variation will most likely perform better because MySQL doesn't know what to do with an OR:

    SELECT MAX(id) AS id FROM
    (SELECT id, id_from AS id_with
    FROM pms
    WHERE id_to = 1
    UNION ALL
    SELECT id, id_to AS id_with
    FROM pms
    WHERE id_from = 1) t
    GROUP BY id_with
    

    Here's how to get the messages for those ids:

    SELECT * FROM pms WHERE id IN
        (SELECT MAX(id) AS id FROM
        (SELECT id, id_from AS id_with
        FROM pms
        WHERE id_to = 1
        UNION ALL
        SELECT id, id_to AS id_with
        FROM pms
        WHERE id_from = 1) t
        GROUP BY id_with)
    
    0 讨论(0)
  • 2021-02-15 18:54

    This query should work:

    SELECT a.*
    FROM pms a
         INNER JOIN (
                     SELECT id_to, id_from, MAX(fecha) AS fecha
                     FROM pms
                     WHERE (id_to = 1 OR id_from = 1)
                     GROUP BY LEAST(id_to, id_from)
                    ) b
                    ON a.fecha = b.fecha AND
                       (a.id_to = b.id_to OR
                       a.id_from = b.id_from);
    

    See example @ sqlfiddle here

    If you have id as PRIMARY KEY and you are logging messages in a chronological order, then it can be further optimized and simplified as:

    SELECT a.*
    FROM pms a
         INNER JOIN (
                     SELECT MAX(id) AS id
                     FROM pms
                     WHERE (id_to = 1 OR id_from = 1)
                     GROUP BY LEAST(id_to, id_from)
                    ) b
                    ON a.id = b.id;
    
    0 讨论(0)
提交回复
热议问题