繁体   English   中英

私人消息系统。 列出每个对话的最后一条消息

[英]Private messaging system. Listing last message of each conversation

让我们说这是数据库结构:

在此输入图像描述

SELECT * FROM `pms` where id_to = 1 or id_from = 1

这将返回他已经收到或发送的所有邮件,

那么如何从用户1可能拥有的每个对话中检索最后一条消息?

PD:当两个用户之间有一条或多条消息时,我将其称为对话

-编辑-

所以鉴于此数据库内容:

在此输入图像描述

我们想获得id 4和6

这假设id是一个自动增量列:

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))

假设你有id_fromid_to索引,这种变化很可能会更好,因为MySQL不知道如何处理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

以下是如何获取这些ID的消息:

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)
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)

此外,如果表中的id_to和id_from足够小以防止语句溢出(id_to + id_from),这里是简单的查询:

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

此查询应该有效:

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);

请参见示例@ sqlfiddle here

如果您将id作为PRIMARY KEY并且按时间顺序记录消息,则可以进一步优化和简化为:

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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM