从每个对话中获取最后一条消息
Posted
技术标签:
【中文标题】从每个对话中获取最后一条消息【英文标题】:Get last message from each conversation 【发布时间】:2016-03-24 09:47:46 【问题描述】:我知道以前有人问过类似的问题,但他们都没有同样的条件,他们的答案不适用于这种情况。
包含消息的表格如下所示:
id | owner_id | recipient_id | content | created
1 | 1 | 2 | Hello | 2015-12-08 20:00
2 | 2 | 1 | Hey | 2015-12-08 20:10
3 | 3 | 1 | You there? | 2015-12-08 21:00
4 | 1 | 3 | Yes | 2015-12-08 21:15
5 | 4 | 1 | Hey buddy | 2015-12-08 22:00
假设我从用户 ID 1 的每个对话中查询最后一条消息,预期结果是:
id | owner_id | recipient_id | content | created
5 | 4 | 1 | Hey buddy | 2015-12-08 22:00
4 | 1 | 3 | Yes | 2015-12-08 21:15
2 | 2 | 1 | Hey | 2015-12-08 20:10
我尝试了很多组合,使用了 JOIN 和子查询,但没有一个给出预期的结果。
这是我尝试过的查询之一,但它不起作用。我相信它甚至不接近我需要的东西。
SELECT
IF ( owner_id = 1, recipient_id, owner_id ) AS Recipient,
(
SELECT
content
FROM
messages
WHERE
( owner_id = 1 AND recipient_id = Recipient )
OR
( owner_id = Recipient AND recipient_id = 1 )
ORDER BY
created DESC
LIMIT 1
)
FROM
messages
WHERE
owner_id = 1
OR
recipient_id = 1
GROUP BY
Recipient;
【问题讨论】:
你的表中是否有唯一键? 是的,我更新了问题(拼错了几个 ID)。 能否请您在问题中包含您尝试过的 SQL 查询? 对不起,太累了,无法给出正确的答案,但您基本上必须按对话的“其他用户”分组,这可以通过case
或if
中的GROUP_BY
语句来实现。在该组中选择 max(id) by,然后选择 where id in (group by query)。
那里,添加了我尝试过的查询之一@summea
【参考方案1】:
select t.*
from
t
join
(select user, max(created) m
from
(
(select id, recipient_id user, created
from t
where owner_id=1 )
union
(select id, owner_id user, created
from t
where recipient_id=1)
) t1
group by user) t2
on ((owner_id=1 and recipient_id=user) or
(owner_id=user and recipient_id=1)) and
(created = m)
order by created desc
example on sqlfiddle
【讨论】:
此查询返回预期结果,非常感谢!虽然我仍在试图弄清楚它是如何工作的。 不客气!如果你愿意,我可以写一些解释 那太好了@splash58【参考方案2】:这应该可以解决问题:
$joins = array(
array('table' => 'conversations',
'alias' => 'Conversation2',
'type' => 'LEFT',
'conditions' => array(
'Conversation.id < Conversation2.id',
'Conversation.owner_id = Conversation2.owner_id',
)
),
array('table' => 'conversations',
'alias' => 'Conversation3',
'type' => 'LEFT',
'conditions' => array(
'Conversation.id < Conversation3.id',
'Conversation.recepient_id = Conversation3.recepient_id',
)
)
);
$conditions = array(
'OR' => array(
array(
'Conversation2.id'=>null,
'Conversation.owner_id' => $ownerId
),
array(
'Conversation3.id'=>null,
'Conversation.recipient_id' => $ownerId
),
)
);
$order = array('Conversation.created'=>'DESC');
$lastConversations=$this->Conversation->find('all',compact('conditions','joins','order'));
假设表的名称是conversations
,而您的模型名称是Conversation
。它基于Retrieving the last record in each group 的公认答案中描述的技术。
【讨论】:
这个好像很接近。到目前为止唯一的问题是结果没有按最新排序。尝试添加“order”参数,但没有解决问题。 @Camilo 我添加了 ORDER BY 子句。 谢谢。我试过了,问题仍然存在。还注意到分组没有按预期工作。我会坚持使用 SQL 的答案,无论如何,谢谢!【参考方案3】:这个解决方案最适合我。
SELECT t1.*
FROM chats AS t1
INNER JOIN
(
SELECT
LEAST(sender_id, receiver_id) AS sender_id,
GREATEST(sender_id, receiver_id) AS receiver_id,
MAX(id) AS max_id
FROM chats
GROUP BY
LEAST(sender_id, receiver_id),
GREATEST(sender_id, receiver_id)
) AS t2
ON LEAST(t1.sender_id, t1.receiver_id) = t2.sender_id AND
GREATEST(t1.sender_id, t1.receiver_id) = t2.receiver_id AND
t1.id = t2.max_id
WHERE t1.sender_id = ? OR t1.receiver_id = ?
Source
【讨论】:
所选答案有什么问题?为什么这对您更有效? 嗯,好问题,据我所知,它并没有按我的意愿检索消息。就像不在订单中或所有我想要的一样以上是关于从每个对话中获取最后一条消息的主要内容,如果未能解决你的问题,请参考以下文章