2014-10-22 57 views
2

IM在其中聊天功能已经实施了一个项目工作。该数据库结构如下:单个SQL查询

表聊天

id    // auto-incrementing message id 
created_by_id // user id of person who wrote this message 
reply_to_id  // id of FIRST message this message is in reply to (0 if new message) 
creation_date // creation timestamp 
text   // message content 

表标签

chat_id   // message id this row corresponds to 
user_id   // user id of person who is an audience of this message 
is_unread  // has the user read this message? 

表用户

id    // auto-incrementing id 
name   // name of user 

个样本数据

CHATS 
1, {ME}, 0, {DATE}, 'This is a new message' 
2, {HIM}, 1, {DATE}, 'This is a reply to the above message' 
3, {HER}, 1, {DATE}, 'So is this one' 
4, {HER}, 1, {DATE}, 'Another reply from HER' 
5, {YOU}, 0, {DATE}, 'This is a different conversation' 

TAGS 
1, {ME}, 0 // ME, HIM and HER as audience, so 3 rows here 
1, {HIM}, 0 
1, {HER}, 0 
2, {HIM}, 0 // ME, HIM and HER here as well 
2, {ME}, 1 
2, {HER}, 0 
3, {HER}, 0 // ME, HIM and HER here as well 
3, {ME}, 1 
3, {HIM}, 1 
4, {YOU}, 0 // YOU and HER as audience, so 2 rows here (ME and HIM should not see this) 
4, {HER}, 1 

这工作得很好我们的目的..此外,表中的遗留应用程序使用,也因此结构不能改变..

现在我要显示这些消息在两个视图中..一个对话视图..和一个对话视图内的消息..

对于对话视图,我需要设计一个SQL查询,使每行包含以下内容(不包括N个子查询):

  • 初始聊天ID(id其中reply_to_id = 0
  • 最近期的聊天ID(在交谈中最大的reply_to_id
  • 最近期的聊天消息
  • 消息(tag.chat_id = chat.id
的收件人列表

有人可以帮我或指导我解决问题吗?具体而言,我需要指导以下:

  • 我可以IF (reply_to_id = 0, id, reply_to_id)找到一个消息对话ID ..我可以按它,以及返回单个对话行。不过我不能检索最新排在这一组..
  • 同样重要的是,我需要找到此消息的所有收件人..作为一个数组或甚至逗号分隔的字符串..但我不知道如何..
  • 我需要稍后实施寻呼解决方案..我敢肯定,这也将决定如何查询写入..

感谢..

awesim


编辑

这是查询即时与工作现在..它工作得很好,但我无法找到一个谈话没有所有收件人单独查询..

SELECT * FROM (
    SELECT 
     IF (c.reply_to_id = 0, c.id, c.reply_to_id) as conv_id, 
     c.*, 
     t.* 
    FROM chats AS c 
    INNER JOIN tags AS t 
     ON t.chat_id = c.id OR t.chat_id = c.reply_to_id 
    WHERE 
     t.user_id = {ME} 
    ORDER BY 
     creation_date DESC 
) AS data 
GROUP BY conv_id 
LIMIT 10 OFFSET 0 

我怎样才能找到这个查询中的收件人列表?

+0

内后加入标签,你需要加入的用户在t.user_id = u.id获得创纪录的为每个用户..不知道如何在一组获得的最后一条消息在一个单一的查询 – CharlieS 2014-10-22 02:44:23

回答

3

假设你的查询不会每次转换提供单行,那么你可以使用GROUP_CONCAT函数来得到最终的聊天的收件人系列:

SELECT {other fields}, GROUP_CONCAT(tags.user_id) AS list_of_recipients 
FROM 
{your query} 
) AS conversation 
INNER JOIN tags on conversation.conv_id=tags.chat_id 
GROUP BY conversation.conv_id 

不过,我实在不明白怎么很好地得到所有其他领域(尽管它可能是可能的)。

这是我写的一个替代方案,但没有经过测试。基本的想法是,我想在对话中找到第一个和最后一个chat_id,然后将所有这些都放在中间。因此,我创建了将用于识别链中第一对的pair1,以及将用于识别椅子中最后一对的pair2。然后,我将第一对中的第二个聊天加入第二个聊天对中。接下来,我从这个新对3中选出第一个chat_id确实是最初聊天的行,而最后一个chat_id确实是最后一个。然后,我通过一个连接接收聊天的正文文本,并通过另一个连接接收所有的接收者。对第一个和最后一个聊天ID进行分组可让我将所有收件人连接成单个值。我使用FIRST()以低廉的价格获取文本。如果您需要将收件人列表加入users表,则可能需要执行该操作,而不是GROUP BY和GROUP_CONCAT。或者,如果你想要一个你可以加入到用户表的名字列表,然后在他们的名字上做GROUP_CONCAT。

HTH

SELECT initial_chat_id, most_recent_chat_id, 
FIRST(most_recent_chat.text), 
GROUP_CONCAT(tags.user_id) AS list_of_recipients_most_recent_chat 
    FROM 
    (
    SELECT prev1_id as initial_chat_id, max(IF(next2_id IS NULL,prev1_id,next2_id)) as most_recent_chat_id 
    FROM 
    (
    (SELECT prev_chat.id AS prev1_id, prev_chat.reply_to_id as prev1_reply_id, 
    next_chat.id AS next1_id 
    FROM chats prev_chat LEFT JOIN 
    chats next_chat on prev_chat.id=next_chat.reply_to_id) AS pair1 
    LEFT JOIN 
    (SELECT prev_chat.id AS prev2_id, prev_chat.reply_to_id as prev2_reply_id, 
    next_chat.id AS next2_id 
    FROM chats prev_chat LEFT JOIN 
    chats next_chat on prev_chat.id=next_chat.reply_to_id) AS pair2 
    ON pair1.next_id=pair2.prev_id) as pair3 
    WHERE 
    prev1_reply_id IS NULL AND next2_id IS NULL) AS conversation 
    INNER JOIN tags ON conversation.most_recent_chat_id=tags.chat_id 
    INNER JOIN chats most_recent_chat ON conversation.most_recent_chat_id=most_recent_chat.id 
    GROUP BY initial_chat_id, most_recent_chat_id, tags.chat_id; 
+0

非常感谢详细的解释..即时通讯试图了解它,并得到它的工作(我的问题声明中有错误,请参阅编辑)..你刚刚在这里教我一些新的东西.. :) – AweSIM 2014-10-22 06:08:47