You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于用户ID获取聊天应用各对话最新消息记录方案咨询

针对你开发聊天应用时,需要按对话用户维度展示最新消息的需求——也就是从和你对话的10位用户中,每个用户只取双方最后一条消息(不管谁发的),我整理了两种实用的解决方案,适配不同的数据库环境:

方案1:使用窗口函数(推荐,适用于MySQL 8.0+、PostgreSQL、SQL Server等)

这种方法逻辑清晰,性能也不错,适合支持SQL窗口函数的数据库。核心思路是把双向对话(比如你发对方、对方发你)归为同一个分组,然后给每个分组内的消息按时间倒序排名,取排名第一的那条就是最新消息。

假设你的消息表是messages,字段包括id(消息ID)、sender_id(发送者ID)、recipient_id(接收者ID)、content(消息内容)、created_at(发送时间);用户表是users,字段有id、name。下面是具体查询代码:

WITH ranked_messages AS (
    SELECT
        -- 确定对话的对方ID
        CASE
            WHEN sender_id = '当前用户ID' THEN recipient_id
            ELSE sender_id
        END AS chat_partner_id,
        -- 关联用户表拿到对方名称
        u.name AS chat_partner_name,
        m.content,
        m.created_at,
        -- 按对话组排名,最新消息排第1
        ROW_NUMBER() OVER (
            PARTITION BY LEAST(sender_id, recipient_id), GREATEST(sender_id, recipient_id)
            ORDER BY m.created_at DESC, m.id DESC
        ) AS rn
    FROM messages m
    JOIN users u ON u.id = CASE
        WHEN m.sender_id = '当前用户ID' THEN m.recipient_id
        ELSE m.sender_id
    END
    -- 只筛选和当前用户相关的消息
    WHERE m.sender_id = '当前用户ID' OR m.recipient_id = '当前用户ID'
)
SELECT chat_partner_id, chat_partner_name, content, created_at
FROM ranked_messages
WHERE rn = 1
ORDER BY created_at DESC;

关键细节说明:

  • LEAST(sender_id, recipient_id)和GREATEST(sender_id, recipient_id):把你和对方的ID按大小排序,确保双向对话被归为同一个分组(比如你ID是1,对方是2,不管是1→2还是2→1,分组键都是(1,2))。
  • ORDER BY m.created_at DESC, m.id DESC:如果两条消息在同一毫秒发送,用消息ID倒序确保取唯一的最新消息。
方案2:分组+子查询(兼容旧版数据库,如MySQL 5.x)

如果你的项目用的是不支持窗口函数的旧版数据库,可以用这种分组查询的方式,先拿到每个对话组的最新消息时间,再匹配对应的消息内容。

SELECT
    CASE
        WHEN m.sender_id = '当前用户ID' THEN m.recipient_id
        ELSE m.sender_id
    END AS chat_partner_id,
    u.name AS chat_partner_name,
    m.content,
    m.created_at
FROM messages m
JOIN users u ON u.id = CASE
    WHEN m.sender_id = '当前用户ID' THEN m.recipient_id
    ELSE m.sender_id
END
WHERE (LEAST(m.sender_id, m.recipient_id), GREATEST(m.sender_id, m.recipient_id), m.created_at) IN (
    -- 子查询:拿到每个对话组的最新消息时间
    SELECT
        LEAST(sender_id, recipient_id),
        GREATEST(sender_id, recipient_id),
        MAX(created_at)
    FROM messages
    WHERE sender_id = '当前用户ID' OR recipient_id = '当前用户ID'
    GROUP BY LEAST(sender_id, recipient_id), GREATEST(sender_id, recipient_id)
)
ORDER BY m.created_at DESC;

优化建议:

如果消息表数据量很大,一定要给sender_id、recipient_id、created_at这三个字段创建联合索引,能大幅提升查询速度。

不管用哪种方案,最终都能实现你要的效果:只展示和你对话的10位用户,每个用户对应一条双方的最新消息,完美解决“从最后两条记录中仅取一条”的需求。

内容的提问来源于stack exchange,提问作者user3886556

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:31:37