我需要在用户之间建立一个简单的内部消息传递系统。
我的桌子:
+--------------+ +---------------------+
| messages | | users |
+----+---------+ +---------------------+
| id | message | | id | username | ...
+----+---------+ +---------------------+
+------------------------------------------------------------------------------+
| users_messages |
+------------------------------------------------------------------------------+
| id | from_usr_id | to_usr_id | msg_id | thread_id | read | sent_at | read_at |
+------------------------------------------------------------------------------+
INT 'thread_id'
表示会话线程,用于对邮件进行分组。
BOOLEAN 'read'
表示用户是否打开/查看了该消息。
我希望按'thread_id'
对邮件进行分组,按'sent_at'
排序,以便我可以按线程向用户显示他的最新消息。我还要计算每个帖子中的消息。
我想为特定用户ID获取类似内容:
+----------------------------------------------------------------------------
| last_messages_by_conversation
+----------------------------------------------------------------------------
| message | from_username | sent_at | count_thread_msgs | count_unread_msg |
+----------------------------------------------------------------------------
TEXT 'message'
是特定'thread_id'
VARCHAR 'from_username'
和DATETIME 'sent_at'
与最新消息相关。
INT 'count_thread_msgs'
和INT 'count_unread_msg'
与线程相关,表示线程中的消息总数和未读消息数。
每一行代表一个线程/对话(按'thread_id'
分组),显示该特定线程的最后一条消息(按'sent_at'
排序)。
答案 0 :(得分:5)
您正在寻找groupwise maximum,首先可以通过users_messages
对thread_id
表进行分组并选择MAX(sent_at)
,然后将结果重新加入users_messages
来找到{{3}}。 {1}}表来查找该最大记录的其他字段。
我发现NATURAL JOIN
是一个非常方便的捷径:
SELECT messages.message,
users.username AS from_username,
t.sent_at,
t.count_thread_msgs,
t.count_unread_msg
FROM users_messages NATURAL JOIN (
SELECT thread_id,
to_usr_id,
MAX(sent_at) AS sent_at,
COUNT(*) AS count_thread_msgs,
SUM(NOT read) AS count_unread_msg
FROM users_messages
WHERE to_usr_id = ?
GROUP BY thread_id
) t JOIN messages ON messages.id = users_messages.msg_id
JOIN users ON users.id = users_messages.from_usr_id
答案 1 :(得分:2)
SELECT
users.id,
users.username,
user_messages.thread_id,
user_messages.unread ,
messages.message
FROM users
LEFT JOIN (SELECT
from_usr_id ,
msg_id,
count(thread_id)) as thread_id,
count(read_at) as unread
FROM user_messages)as user_messages on user_messages.from_usr_id = users.id
LEFT JOIN messages on messages.id = user_messages.msg_id
答案 2 :(得分:2)
您可以尝试此解决方案:
SELECT c.message,
d.username AS from_username,
b.sent_at,
a.count_thread_msgs,
a.count_unread_msg
FROM (
SELECT MAX(id) AS maxid,
COUNT(*) AS count_thread_msgs,
COUNT(CASE WHEN `read` = 0 AND <uid> = to_usr_id THEN 1 END) AS count_unread_msg
FROM users_messages
WHERE <uid> IN (from_usr_id, to_usr_id)
GROUP BY thread_id
) a
JOIN users_messages b ON a.maxid = b.id
JOIN messages c ON b.msg_id = c.id
JOIN users d ON b.from_usr_id = d.id
ORDER BY b.sent_at DESC
这会在用户<uid>
启动或参与的每个线程中获取最新消息。
最新消息基于每个thread_id的最高id
。
此解决方案做出以下假设:
id
中的users_messages
是每个新行的唯一自动递增int。如果线程可以包含两个以上的用户,则需要稍微调整查询,以便获得准确的计数聚合。
答案 3 :(得分:1)
试试这个并告诉我们,为您的$$
改变user ID
..
select u.username,msg.message,m.sent_at,
(select count(*) from user_message where read=0 and to_usr_id=$$) as count_thread_msgs,
(select count(*) from user_message where to_usr_id= $$) as count_unread_msg
from users as u join user_messages as m
on u.id=m.id where u.id=$$
join messages as msg on msg.id=m.id
group by u.id;`
答案 4 :(得分:0)
尝试此查询 -
SELECT
m.message,
u.username from_username,
um1.sent_at,
um2.count_thread_msgs,
um2.count_unread_msg
FROM users_messages um1
JOIN (
SELECT
thread_id,
MAX(sent_at) sent_at,
COUNT(*) count_thread_msgs,
COUNT(IF(`read` = 1, `read`, NULL)) count_unread_msg
FROM users_messages GROUP BY thread_id) um2
ON um1.thread_id = um2.thread_id AND um1.sent_at = um2.sent_at
JOIN messages m
ON m.id = um1.msg_id
JOIN users u
ON u.id = um1.from_usr_id
-- WHERE u.id = 100 -- specify user id here
您的问题的答案:
...WHERE u.id = 100
。messages
和users
),并且可能有多条记录具有相同的thread_id
。为避免这种情况,您应该按thread_id
字段对结果集进行分组,并使用聚合函数来获得单个结果,例如使用GROUP_CONCAT函数。