我正在开发一个已经实现了聊天功能的项目..数据库结构如下:
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
其中reply_to_id = 0
)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 :(得分: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,然后将所有的chat_id放在中间。所以我创建了用于识别链中第一对的pair1,以及用于识别椅子中最后一对的pair2。然后我加入第一对中的第二个聊天到第二对中的第一个聊天。接下来,我从这个新的pair3中选出第一个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;