繁体   English   中英

在一个查询中从对话中选择所有发给用户的消息

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM