从数据库Mysql/MariaDB获取正确的数据集

从数据库Mysql/MariaDB获取正确的数据集,mysql,sql,date,group-by,greatest-n-per-group,Mysql,Sql,Date,Group By,Greatest N Per Group,从一个表中考虑以下数据 从消息中选择* +--+------+------+--------------------------------+------+ |id | did | U从| did | U到|消息|时间戳| +--+------+------+--------------------------------+------+ |28 | 3369377501 | 336502446 |嘿| 15854655342| |29 | 336502446 | 3369377501 |你在干

从一个表中考虑以下数据

从消息中选择*

+--+------+------+--------------------------------+------+ |id | did | U从| did | U到|消息|时间戳| +--+------+------+--------------------------------+------+ |28 | 3369377501 | 336502446 |嘿| 15854655342| |29 | 336502446 | 3369377501 |你在干什么|1585465349 | |30 | 3369377501 | 336502446 |开车,干什么1585465369 | |31 | 336502446 | 3369377501 |开车和发短信1585465375 | |32 | 3369377501 | 336502446 |嗯,你确定你应该这么做吗1585465395 | |39 | 336502446 | 3369377501 |是的,因为我是一名短信专家| 15854655500| |40 | 336502446 | 3369377501 |短信专家| 1585465517| |42 | 336502446 | 3369377501 |拒绝你认为会破坏的想法| 15854655550| |43 | 336502446 | 3369377501 |因为我心烦意乱1585465559 | |44 | 336502446 | 3369377501 |当我在文本上活跃起来时,我在方向盘后面完成多个任务的效果最好| 15854655577| |50 | 336502446 | 3369377501 |发短信很酷| 1585518726| |51 | 3369377501 | 336502446 |我同意| 1585518740| |52 | 336502446 | 3369377501 |嘿| 158557071| |53 | 3369377501 | 336502446 |嘿| 1585573087| |54 | 336502446 | 3369377501 |怎么了| 1585576304| +--+------+------+--------------------------------+------+ 如果这是两个人之间的对话,并且我希望获得对话中ethier person的最后一条消息,我将运行查询

从消息中选择*,其中id在“从消息中选择最大id”组中由did_FROM和did_to='3365024246'指定,或id在“从消息中选择最大id”组中由did_FROM和did_FROM='3365024246'指定

假设

DID:3365024246是已登录的用户

我们不知道对话中的其他人是谁。我们正在搜索并获取对话列表,并显示登录者或其他人的最后一条消息

问题

当前查询将返回

+--+------+------+-----+------+ |id | did | U从| did | U到|消息|时间戳| +--+------+------+-----+------+ |54 | 336502446 | 3369377501 |怎么了| 1585576304| |53 | 3369377501 | 336502446 |嘿| 1585573087| +--+------+------+-----+------+ 期待什么

+--+------+------+-----+------+ |id | did | U从| did | U到|消息|时间戳| +--+------+------+-----+------+ |54 | 365024246 | 3369377501 |怎么了| 1585576304| +--+------+------+-----+------+
如果您运行的是MySQL 8.0,则可以使用窗口函数:

select *
from (
    select 
        m.*, 
        row_number() over(
            partition by least(did_from, did_to), greatest(did_from, did_to)
            order by timestamp desc
        ) rn
    from messages m
    where 3365024246 in (did_from, did_to)
) t 
where rn = 1
重要的是由最小和最大的对等方进行划分,这避免了将相同会话的消息放在同一组中,而不管是谁发送或接收的

在早期版本中,可以使用相关子查询进行筛选:

select m.*
from messages m
where 
    3365024246 in (m1.did_from, m1.did_to) 
    and m.id = (
        select m1.id
        from messages m1
        where               
            and least(m1.did_from, m1.did_to) = least(m.did_from, m.did_to)
            and greatest(m1.did_from, m1.did_to) = greatest(m.did_from, m.did_to)
        order by m1.timestamp desc
        limit 1
    )

这对我们想要实现的目标非常有效,我希望我能投票支持这一点