我目前正在努力处理查询并需要一些帮助。
我有两张桌子:
messages {
ts_send,
message,
conversations_id
}
conversations {
id
}
我想从每个对话中选择具有最新ts_send的消息。 所以如果我得到3个对话,我最终会收到3条消息。
我开始编写以下查询,但我很困惑如何比较每次会话的最大值(ts_send)。
SELECT c.id, message, max(ts_send) FROM messages m
JOIN conversations c ON m.conversations_id = c.id
WHERE c.id IN ('.implode(',', $conversations_ids).')
GROUP by c.id
HAVING max(ts_send) = ?';
一般来说,查询可能是错误的,只是想分享我的尝试。
关心基督徒
答案 0 :(得分:3)
MySql比相关子查询更好地优化JOIN,因此我将介绍连接方法。
第一步是获得每个对话的最大ts_send
:
SELECT conversations_id, MAX(ts_send) AS ts_send
FROM messages
GROUP BY conversations_id;
然后,您需要JOIN
这回到消息表以获取实际消息。 conversation_id和MAX(ts_send)上的连接确保每次会话仅返回最新消息:
SELECT messages.conversations_id,
messages.message,
Messages.ts_send
FROM messages
INNER JOIN
( SELECT conversations_id, MAX(ts_send) AS ts_send
FROM messages
GROUP BY conversations_id
) MaxMessage
ON MaxMessage.conversations_id = messages.conversations_id
AND MaxMessage.ts_send = messages.ts_send;
除非你还需要在没有消息的情况下返回对话,否则上面的内容应该可以帮助你。在这种情况下,您需要从conversations
和LEFT JOIN中选择以上查询:
SELECT conversations.id,
COALESCE(messages.message, 'No Messages') AS Message,
messages.ts_send
FROM conversations
LEFT JOIN
( SELECT messages.conversations_id,
messages.message,
Messages.ts_send
FROM messages
INNER JOIN
( SELECT conversations_id, MAX(ts_send) AS ts_send
FROM messages
GROUP BY conversations_id
) MaxMessage
ON MaxMessage.conversations_id = messages.conversations_id
AND MaxMessage.ts_send = messages.ts_send
) messages
ON messages.conversations_id = conversations.id;
修改强>
选择所有会话而不管他们是否有消息的后一种选择将更好地实现如下:
SELECT conversations.id,
COALESCE(messages.message, 'No Messages') AS Message,
messages.ts_send
FROM conversations
LEFT JOIN messages
ON messages.conversations_id = conversations.id
LEFT JOIN
( SELECT conversations_id, MAX(ts_send) AS ts_send
FROM messages
GROUP BY conversations_id
) MaxMessage
ON MaxMessage.conversations_id = messages.conversations_id
AND MaxMessage.ts_send = messages.ts_send
WHERE messages.ts_send IS NULL
OR MaxMessage.ts_send IS NOT NULL;
在此感谢spencer7593,他提出了上述解决方案。
答案 1 :(得分:1)
如果您只想获得每个唯一ts_send
中最大的conversations_id
,则可以使用以下代码:
SELECT *
FROM messages
WHERE CONCAT(conversations_id, '_', ts_send) IN ( SELECT CONCAT(conversations_id, '_', MAX(ts_send))
FROM messages
GROUP BY conversations_id );
此代码的作用是,它会创建conversations_id
对和最大ts_send
对。然后将其与整个表中的所有对进行比较。
答案 2 :(得分:1)
SELECT c.id, m.message, m.ts_send
FROM conversations c LEFT JOIN messages m
ON c.id = m.conversations_id
WHERE m.ts_send =
(SELECT MAX(m2.ts_send)
FROM messages m2
WHERE m2.conversations_id = m.conversations_id)
LEFT JOIN确保每个会话都有一行,无论是否有消息。如果您的模型中无法实现,则可能没有必要。在那种情况下:
SELECT m.conversations_id, m.message, m.ts_send
FROM messages m
WHERE m.ts_send =
(SELECT MAX(m2.ts_send)
FROM messages m2
WHERE m2.conversations_id = m.conversations_id)
答案 3 :(得分:1)
SELECT c.id, m.message, m.ts_send
FROM
messages m, conversations c,
(SELECT conversations_id, MAX(ts_send) as ts_send
from messages
group by conversations_id) s
where s.conversations_id=m.conversations_id and s.ts_send=m.ts_send and
c.id=m.conversations_id
答案 4 :(得分:0)
我认为这就是你所说的。
mysql> create table messages (ts_send int, message char(30), id int);
Query OK, 0 rows affected (0.01 sec)
mysql> create table conversations (id int);
Query OK, 0 rows affected (0.01 sec)
现在有些数据。
mysql> insert into conversations values ( 1), (2), (3), (4);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> insert into messages values ( 4, 'abc', 1 ),
(5, 'pqr', 1),
(4, 'abc', 2),
(5, 'abc', 3),
(6, 'abc', 4);
Query OK, 5 rows affected (0.01 sec)
Records: 5 Duplicates: 0 Warnings: 0
然后是查询。
mysql> select messages.id, message, ts_send
from messages
where ROW(id, ts_send) in
(select messages.id, max(ts_send)
from messages, conversations
where messages.id = conversations.id group by id);
+------+---------+---------+
| id | message | ts_send |
+------+---------+---------+
| 1 | pqr | 5 |
| 2 | abc | 4 |
| 3 | abc | 5 |
| 4 | abc | 6 |
+------+---------+---------+
4 rows in set (0.00 sec)
mysql>
右?
* 这是为了反映Marty McVry的评论。