![](/img/trans.png)
[英]MySql query for selecting latest message from the conversation and messages table join
[英]Selecting all messages to user from conversation in one query
我为数据方案如下的用户提供了一个“消息”系统:
Table: Messages - Message_id PRI AI key
Message_id Message_text From_user_id Date Conversation_ID
1 'a' 1 1
2 'b' 2 1
3 'c' 5 1
4 'f' 18 2
5 'e' 1 8
Table:Conversations
Conversation_id Subject
1 'random'
2 'hi'
8 'yolo'
Table:Participants
Conversation_ID User_id Ignored - TINYINT(1)
1 1 0
1 2 0
1 5 1
2 18 0
2 223 0
8 1 0
8 19 0
它的工作方式是每个对话都有其自己的ID,并且该对话下的所有消息都记录在消息中,该列的session_id列将消息与会话相关联。 用户可以“忽略”对话,因此在参与者中,我们有一个TINYINT列,用于确定用户是否已忽略对话。
我正在尝试获得一个查询,该查询可以首先返回对话行,然后在对话行下方返回对话中的消息,这些消息都是针对查询用户的。 where子句还应该是用户没有忽略对话。 因此,如果我们要查找“对话”以及User_id 1的相应消息,则返回结果将如下所示:
Conversation_id Subject Message_id Message_text From_user_id
1 'random' null null null
1 1 'a' 1
1 2 'b' 2
1 3 'c' 5
8 'yolo' null null null
5 'e' 1
基本上在伪代码中,我想做的是:
SELECT conversation_id, conversations.subject FROM participants WHERE user_id = '1' AND ignored = 0 LEFT JOIN conversations ON conversations.conversation_id = participants.conversation_id AND participants.ignored = 0
UNION GROUP BY messages.conversation_id
SELECT message_id, message_text, from_user_id FROM messages WHERE messages.conversation_id = conversation.conversation_id
不幸的是,我在UNION小组遇到了困难,因为我不能将所有的增长都融合在一起。 我一直在尝试在一个查询中执行此操作(因此选择null来弥补会话没有message_text且消息没有主题的事实),但是不知道任何MySQL代码可以执行UNION GROUP BY那种。 是否可以在一个查询中执行此操作而不必解析PHP中的所有session_id,然后相应地加载消息?
我相信您可以使用1个包含子查询的查询来做到这一点:
SELECT *
FROM (
SELECT Conversation_id
FROM Participants
WHERE User_id = 1 AND Ignored = 0
GROUP BY Conversation_id
) AS C_IDs
INNER JOIN Conversations AS C ON C_IDs.Conversation_id = C.Conversation_id
INNER JOIN Messages AS M ON C_IDs.Conversation_id = M.Conversation_id
WHERE C_IDs.Conversation_id = 1
这应该返回如下结果:
C_IDs.Conversation_id C.Conversation_id C.Subject M.Message_id M.Message_text M.From_user_id M.Date M.Conversation_ID
1 1 'random' 1 'a' 1 1
1 1 'random' 2 'b' 2 1
1 1 'random' 3 'c' 5 1
如果在末尾删除WHERE子句并更改SELECT:
SELECT C.Conversation_id AS Conversation_id, C.Subject AS Subject, M.Message_id AS Message_id, M.Message_text AS Message_text, M.From_user_id AS From_user_id
FROM (
SELECT Conversation_id
FROM Participants
WHERE User_id = 1 AND Ignored = 0
GROUP BY Conversation_id
) AS C_IDs
INNER JOIN Conversations AS C ON C_IDs.Conversation_id = C.Conversation_id
INNER JOIN Messages AS M ON C_IDs.Conversation_id = M.Conversation_id
结果应该是这样的:
Conversation_id Subject Message_id Message_text From_user_id
1 'random' 1 'a' 1
1 'random' 2 'b' 2
1 'random' 3 'c' 5
8 'yolo' 5 'e' 1
如果要在结果集中进行遍历,则只需创建一个变量即可跟踪对话ID。 将值初始化为NULL,然后添加if语句,以检查值是否已更改。 如果有,则写出新的对话详细信息,然后将id设置为新的id。
恕我直言,这是一种非常糟糕的方式。 只需进行两个简单的查询即可,而不是将其弄得一团糟。 第一次查询对话,第二次查询与对话相关的所有消息。 假设您正在使用PDO,这是两个需要的查询:
$q1 = $conn->prepare('SELECT Conversation_ID FROM `participants` WHERE `User_id` = ? AND `Ignored` = 0');
$q1->execute(array($userID));
$conversations = array_map(function($item) { return $item->Conversation_ID; }, $q1->fetchAll());
$q2 = $conn->prepare('SELECT * FROM messages WHERE `Conversation_ID` IN (' . implode(',', $conversations) . ') AND `User_id` != ?');
$q2->execute(array($userID));
$messages = $q2->fetchAll();
此时, $messages
包含除对话主题之外的所有所需信息,但是您可以在$q1->fetchAll()
返回的内容中找到这些主题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.