SQL - 如何选择涉及多个表的数据?

时间:2015-12-18 19:05:22

标签: mysql sql

RDMS:MySQL

我正在设计一个私人消息传递线程系统,并为消息传递系统配置了以下架构(简化)。我需要选择具有已知ID(我们会说' 1')的帐户,对话中发送的最后一条消息以及另一个帐户的用户名的每个对话帐号' 1'正在聊天。通过对话ID分组。 (想象像Facebook这样的收件箱页面)

我的SQL知识是有限的(我将花费周末推进它)但同时有人有一个查询可以完成工作吗?

提前致谢。如果您需要更多信息,请告诉我。

架构 enter image description here

编辑:我相信我可能找到了解决方案(仍然需要进行适当的测试)。 我还在接受答案,因为我不确定这是最好的路线。我已经回顾了当前发布的答案,他们让我朝着正确的方向前进,但到目前为止还没有找到正确的结果。

以下是我的想法。

SELECT account_has_conversations.account_id, messages.*, account.username FROM messages, account, account_has_conversations WHERE account_has_conversations.conversation_id IN

(
SELECT account_has_conversations.conversation_id FROM account_has_conversations WHERE account_has_conversations.account_id = '1'
)

AND account_has_conversations.account_id != '1' AND account_has_conversations.account_id = account.account_id
AND account_has_conversations.conversation_id = messages.conversation_id
GROUP BY account_has_conversations.conversation_id

(我可能应该创建一些别名哈哈)

4 个答案:

答案 0 :(得分:2)

首先,您在图片架构中的任何表格中都没有任何文本字段 - 因此我不知道您在哪里存储实际的邮件内容或如何检索它。也就是说,此查询应该适合您,您只需添加所需的字段即可。

这将为您提供所有选定用户对话的用户名,收到的最后一条消息以及发送用户名。我将ASSUME消息内容在消息表中,并存储在名为“message_text”的字段中:

DECLARE @AccountID int = 1 //For testing, but this should be parameterized


SELECT  A.username as [User],
    A2.username as [SendingUser]
    M.message_text as [LastMessage]
FROM account A
JOIN account_has_conversations AHC
    ON A.account_id = AHC.account_id
JOIN conversation C
    ON AHC.conversation_id = C.conversation_id
JOIN
    (
        Select 
        sender_account_id,
        conversation_id,
        message_text,
        row_number() over(partition by conversation_id order by time_sent desc) as rn 
        FROM messages 
    ) as M
    ON C.conversation_id = M.conversation_id
    AND M.sender_account_id <> @AccountID //This prevents a circular join in case the last message was sent by the user.  You may not need this, but it's impossible to tell based on the information you provided.
JOIN account A2
    ON M.sender_account_id = A2.account_ID
WHERE rn = 1
AND A.account_id = @AccountID

答案 1 :(得分:0)

我已经对此进行了测试,但也许这会让你朝着正确的方向前进。

Select m.* 

from account a
inner join account_has_conversation ahc
on (a.account_id = account_id)
inner join messages m
on (ahc.conversation_id = m.conversation_id)

where a.account_id = 1

我想补充一下:

  • 您的会话表似乎没有任何价值。
  • Group By很棒,但您还需要将所有结果压缩。我的意思是,如果你想将十行压缩成一行(按照列中所有行在该列中具有相同值的列之一进行分组),则需要在聚合函数中包含所有其他列。 / LI>

答案 2 :(得分:0)

SELECT a.username, m.*, c.* FROM account a, messages m, conversation c 
WHERE a.account_id = m.sender_account_id AND m.conversation_id = c.conversation_id

答案 3 :(得分:0)

基于下面的新架构。 messages(msg_id, con_id, message, time_sent, status)

acc(acc_id, username)

con(con_id)

conrel(con_id, acc_id)

(从手机输入,所以忽略任何较小的错误)。

SELECT distinct msg.message, conrel.con_id, acc.username FROM messages AS msg INNER JOIN conrel ON conrel.con_id = msg.con_id INNER JOIN acc ON conrel.acc_id=acc.acc_id where conrel.con_id IN (SELECT DISTINCT con_id FROM connrel WHERE acc_id=1) ORDER BY msg.time_sent DESC

可以根据需要进一步改进或改变解决方案。另外请记住使用上面的INNER查询的逗号分隔结果,因为INNER查询较慢,但是当它们以1,4,5这样的ID传递时,它们会变快。