1

在过去的几个小时里,我被这个查询卡住了,我非常需要有人帮我解决这个问题。我试图完成我的私人消息系统,但我迷失在数据库表中。我为系统创建了三个表,它们如下:

CONVERSATION(**conversation_id**, subject)

CONVERSATION_MEMBER(**conversation_id**, **user_id**, conversation_last_view, conversation_deleted)

CONVERSATION_MESSAGE(**message_id**, conversation_id, user_id, message_date, message_text)

好的,所以在我获取特定用户的所有对话的功能中,我正在获取主题、日期,最后我想向用户展示他/她正在与谁交谈。我写了以下查询:

SELECT
   c.conversation_id,
   c.conversation_subject, 
   MAX(cmes.message_date) AS conversation_last_reply, 
FROM conversation c, conversation_member cmem, conversation_message cmes
WHERE c.conversation_id = cmes.conversation_id
AND c.conversation_id = cmem.conversation_id                          
AND cmem.user_id = {$_SESSION['user_id']}
AND cmem.conversation_deleted = 0
GROUP BY c.conversation_id
ORDER BY conversation_last_reply DESC

而且,最后我试图获取用户的名字和姓氏(对话中的另一个用户),但我迷失了如何做到这一点。我试图创建另一个函数来获取对话 id,同时遍历第一个查询的结果,并返回用户的名字和姓氏,但没有成功。

顺便说一句,对于用户,我还有另一张桌子......我想我不必告诉你。好的谢谢。

4

5 回答 5

2
$sql = "SELECT (user.forename, user.surname, other_fields...)
          FROM conversation
    INNER JOIN conversation_member
            ON conversation.conversation_id = conversation_member.conversation_id
    INNER JOIN conversation_message
            ON conversation.conversation_id = conversation_message.conversation_id
    INNER JOIN users_table /* replace this with the name of your user table */ AS user
            ON user.user_id = conversation_member.user_id
         WHERE user.user_id = :userid
           AND conversation_member.conversation_deleted = 0
      GROUP BY conversation.conversation_id;"

$query = $db->prepare($sql);
$query->bindParam(':userid', $userid, PDO::PARAM_INT);
$query->execute();
$results = $query->fetchAll();
$user = $results[0]["user"]; //stores array of user fields (forename, surname, etc)
于 2012-04-17T23:37:49.613 回答
1

如果您能够自己构建查询的其余部分,我不明白为什么您无法获取用户的名字和姓氏?

尝试以下方式:

SELECT cmem.user_id, u.first_name,  u.last_name, c.conversation_id, c.conversation_subject, MAX(cmes.message_date) AS conversation_last_reply  
FROM conversation c  
INNER JOIN conversation_member cmem on c.conversation_id=cmem.conversation_id  
INNER JOIN conversation_message cmes on c.conversation_id=cmes.conversation_id  
INNER JOIN users u on u.user_id = cmem.user_id
WHERE cmem.user_id = {$_SESSION['user_id']} AND cmem.conversation_deleted = 0  
GROUP BY cmem.user_id, u.first_name, u.last_name, c.conversation_id, c.conversation_subject

现在,我认为您还应该重新考虑您的数据库结构,以便不需要所有这些连接。我看到几个问题。一,您的数据库似乎过度规范化。为什么你有一个单独的“对话”表,它只有两个字段,对话 ID 和主题?在我见过的任何消息系统中,主题始终可见,因此您始终必须加入对话表才能获取主题字段。无论如何,conversation_id 都在其他所有表中。只需将主题字段添加到消息表并消除对话表(如果它只包含它),规范化并不总是一件好事。

其次,为什么要为已删除的消息设置标志而不是删除它们?我也从未见过可以让我恢复已删除的消息的消息系统。至少,如果您出于某种原因想要保留它们,您应该将它们移动到存档表中,以便您运行的主表选择关闭时不必处理通过无意义的“已删除”解析的性能损失"条目。

最后,conversation_member 表到底是什么?根据我的解释,它应该代表对话的成员,因为它有一个 user_id。为什么对话的单个成员会出现对话删除标志?如果有的话,它应该在对话表中。有了这个改进,剩下的唯一字段是 conversation_last_view,真的没人关心。更重要的是conversation_last_post,它可以很容易地从线程中发布的最后一条消息的时间戳推导出来。

最后,如果您只想查看附加到查询中的名字和姓氏,只需加入 users 表并显示这两个条目即可。如果我提供的 SQL 查询不能直接运行,我应该会让你关闭,我懒得复制你的数据库并自己尝试。但是,我认为您也应该真正考虑数据库的整体设计,这样您就不会遇到不必要的性能问题。

于 2012-04-18T00:24:02.280 回答
1
SELECT
   c.conversation_id,
   c.conversation_subject,
   user.firstname,
   user.lastname,
   MAX(cmes.message_date) AS conversation_last_reply, 
FROM conversation c, conversation_member cmem, conversation_message cmes, user_tablename user
WHERE c.conversation_id = cmes.conversation_id
AND c.conversation_id = cmem.conversation_id                          
AND cmem.user_id = {$_SESSION['user_id']}
AND cmem.conversation_deleted = 0
AND user.user_id_column = whatever.you_used_as_foriegn_key
GROUP BY c.conversation_id
ORDER BY conversation_last_reply DESC

假设列名是这样的

于 2012-04-17T23:29:50.130 回答
1

您需要再次加入“conversation_member”表,这一次,选择其他用户的 id,其中应用了相同的 conversation_id 和 message_id:

SELECT
    c.conversation_id,
    c.conversation_subject, 
    MAX(cmes.message_date) AS conversation_last_reply,
    cmem2.user_id AS other_user_id
    CONCAT(usr_tbl.firstname, ' ', usr_tbl.lastname) AS other_user_name
FROM conversation c
    JOIN conversation_member cmem
    JOIN conversation_message cmes
    JOIN conversation_member cmem2
    JOIN users_table usr_tbl

ON  c.conversation_id = cmes.conversation_id 
AND c.conversation_id = cmem.conversation_id                          
AND cmem.user_id = {$_SESSION['user_id']}
AND cmem.conversation_deleted = 0

AND c.conversation_id = cmem2.conversation_id                          
AND cmem2.user_id = {$_SESSION['other_user_id']}
AND cmem2.conversation_deleted = 0

GROUP BY c.conversation_id
ORDER BY conversation_last_reply DESC
于 2012-04-17T23:58:22.933 回答
0

要回答以下问题:查找对话中的所有用户,减去当前用户:

    SELECT (users.forename, users.surname)
      FROM conversation_members AS members
INNER JOIN users_table AS users
        ON members.user_id = users.user_id
     WHERE members.conversation_id = :conversationid
       AND NOT users.user_id = :userid

:userid当前用户在哪里,:conversationid是有问题的对话。

于 2012-04-18T01:07:54.717 回答