【问题标题】:PHP, MySQL: How to get the user's first and last namePHP,MySQL:如何获取用户的名字和姓氏
【发布时间】:2012-04-29 08:17:48
【问题描述】:

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

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,同时遍历第一个查询的结果,并返回用户的名字和姓氏,但没有成功。

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

【问题讨论】:

  • 您实际上并没有从 conversation_member 中选择任何内容
  • 你想说什么?我不知道我将如何选择任何东西,因为我正在做 cmem.user_id = sessionID。您想就您的答案多说一些吗?
  • 添加了正确答案,希望对您有所帮助

标签: php mysql fetch


【解决方案1】:
$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)

【讨论】:

  • 您的查询将如何返回用户的名字和姓氏?我不明白。
  • @Darko 只要你将表格加入到一起,你就可以选择它们的字段(见上文)
  • 问题是这将返回登录用户的名字和姓氏,而不是来自对话中的其他参与者......
  • @Darko 但是您只存储了一个用户 ID?我误解了你的问题吗?您只需要在一次对话中找到所有用户?
  • 在会话中我只持有登录用户。因此,登录和其他用户之间的对话是可能的。两个用户 ID 都存储在该特定对话的 conversation_member 表中。我想要做的是取另一个用户的名字和姓氏(不是登录的那个,而是另一个)
【解决方案2】:
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

假设列名是这样的

【讨论】:

  • 我不将用户存储在 conversation_member 表中,我只存储他们的 ID。所以,我需要连接第四个表(即用户表)。即使是这样,您的回答也会返回登录用户的名字和姓氏,而不是他正在与之交谈的用户......
  • 在这种情况下添加最终用户表并将对 cme​​m.firstname 的引用更改为新表,没有问题
  • 您的意思是,将 cmem.firstname 更改为 user.firstname,仅此而已?它返回一个错误的用户......我需要在 WHERE 子句中以某种方式连接它们,这就是我被卡住的地方......
  • 我稍微调整了一下,用你自己的替换表引用
  • 我仍然得到一个错误的值。现在它正在返回当前登录的用户。
【解决方案3】:

您需要再次加入“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

【讨论】:

  • 好吧,我实际上不知道对话中的另一个参与者是谁。我不将它存储在会话中。我需要想办法把它拿走……
【解决方案4】:

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

尝试以下方式:

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 查询不能直接运行,我应该会让你关闭,我懒得复制你的数据库并自己尝试。但是,我认为您也应该真正考虑数据库的整体设计,这样您就不会遇到不必要的性能问题。

【讨论】:

  • 根据您的建议,我实际上会得到登录用户的名字和姓氏。这就是我试图向加入这个问题的每个人解释的内容。为了回答您的建议,我将看看删除对话表并做其他事情,但是关于已删除消息的标志,我不能只删除对话。因为如果其中一个用户删除了对话,那么另一个配置文件中的对话也将被删除。当两个用户都将对话设置为已删除时,我完全删除了对话。
  • 是的,但我认为你想多了。有时在考虑如何做之前先考虑为什么是很重要的。您是否曾经使用过一个消息系统来“删除”您的线程?如果在没有其他用户验证的情况下无论如何都不会删除它,您自己是否还会费心使用此功能?一个人想要删除它而另一个人也想删除它的可能性有多大?另外,为什么删除是在会话级别而不是消息级别?
  • 好吧,删除部分:)我真的很想就实际问题获得帮助..用户不会知道对话实际上并没有被删除,因为在我设置他的“已删除”之后flag" 设置为 1 比如说,它不会出现在他的对话窗口中。在其他用户也将其设置为 1 后,我将其完全删除。如果您真的给我一些建议(如果您愿意,可以在整个系统上)而不是批评我,我将不胜感激:)
  • 建设性的批评没有错,这就是这个地方的用途:)。如果我被认为是侮辱性的,我道歉,那不是我的意图。无论如何,我的建议是完全摆脱删除功能。通常,没有理由允许某人删除消息。在消息系统的上下文中,如果他们不希望它在那里,他们就不会阅读它。您真正想要删除消息的唯一时间是您不想让任何人看到它。如果你想启用它,你必须让他们为所有人删除它。
  • 所以简而言之,我的建议是删除删除对话的功能,因为它不直观且不必要。如果您真的希望用户能够删除他们的消息,我会对其进行更改,以便他们可以删除单个消息(仅当他们显然拥有该消息时)而不是整个对话,并且它将对所有用户生效。
【解决方案5】:

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

    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 是相关对话。

【讨论】:

  • 我想这样我需要创建单独的查询。因为否则会自相矛盾。也许我应该通过调用一个单独的函数或我不知道的东西再试一次。
  • 看看这里,看看我如何将许多表连接在一起以获取其信息:stackoverflow.com/questions/10154466/…。另请参阅我关于电子邮件系统结构的回答:stackoverflow.com/questions/10175076/…@Darko
  • 哇...不错 :D 你介意给我这个查询的数据库模式吗?也谢谢你的第二个帖子。我真的很感激。
  • @Darko 您可以通过表/列名称来判断!但我会编辑答案以发布架构
  • @Darko 好的,它已更新,再次检查链接。不过我必须警告你,我的代码未经测试,从那时起我已经更新了架构(我已经为你发布了),但是链接中的查询没有更新。
猜你喜欢
  • 2019-01-06
  • 1970-01-01
  • 2016-08-01
  • 1970-01-01
  • 2019-01-27
  • 2020-02-15
  • 2021-01-16
  • 1970-01-01
  • 2017-06-26
相关资源
最近更新 更多