SQL 选择接收和发送的每个会话的最新消息

Hal*_*100 1 mysql sql greatest-n-per-group

这个问题SQL select only rows with max value on a column不能解决我的问题,尽管它已被标记为重复。

当它们没有这样的约束时,它假定我的列from_id并且to_id是主键(请参阅下面提供的代码)。如果它们是主键,我就无法将我的消息存储在同一个表中。因此,此答案的 SQL 查询多次打印所有重复项,这不是我想要的。请参阅下面的预期行为。

预期行为:我需要从所有对话中选择最新的消息,无论用户是发件人、收件人还是两者兼而有之。每个对话/线程应该只显示一次

示例:查询此表时,我的 SQL 语句应该只输出 msg3 和 msg4,忽略 John 和 Alice 之前交换的所有消息。

在此处输入图片说明

这是我能写的最接近的查询。问题是此查询仅选择用户收到消息的对话。我一直在添加对话,其中用户只是发件人(他没有收到任何回复)到选择。

SELECT * FROM messages where `to_id` = '1' GROUP BY `from_id` ORDER BY `send_date` ASC
Run Code Online (Sandbox Code Playgroud)

这里是usersmessages表:

CREATE TABLE users (
    id INT(11) AUTO_INCREMENT PRIMARY KEY, 
    name VARCHAR(128) NOT NULL
);

CREATE TABLE messages (
    id INT(11) AUTO_INCREMENT PRIMARY KEY, 
    to_id INT(11) NOT NULL,   //recipient id to match to current user id
    from_id INT(11) NOT NULL, //sender id to match to current user id
    send_date DATETIME DEFAULT CURRENT_TIMESTAMP,
    content TEXT
);
Run Code Online (Sandbox Code Playgroud)

问题:如何使用单个 SQL 查询执行此操作?或者我应该使用三个表而不是一个表来更改我的数据结构?

Gor*_*off 6

我会首先得到ID。您可以使用least()and执行此操作greatest()

select least(m.to_id, m.from_id) as id1,
       greatest(m.to_id, m.from_id) as id2, max(m.id) as max_id
from messages m
group by id1, id2;
Run Code Online (Sandbox Code Playgroud)

然后,您可以join通过返回来获取有关该消息的完整信息:

select m.*
from messages m
where m.id in (select max(m.id) as max_id
               from messages m
               group by least(m.to_id, m.from_id), greatest(m.to_id, m.from_id)
              );
Run Code Online (Sandbox Code Playgroud)

注意:在旧版本的 MySQL 中,将子查询放在from子句中使用join效率更高。