我正在为我的应用构建一个小型消息传递系统,主要的想法是拥有2个表。 表1消息
Id,sender_id,title,body,file,parent_id
这是存储消息的地方,与谁分开将接收消息以允许多个收件人。
父母如果是回复则链接到父消息,而文件是用于存储附加到消息的单个文件的blob
表2 message_users
Id,thread_id,user_id,is_read,stared,deleted
将父线程链接到目标用户,
现在让一个用户可以查看我可以做的未读消息的数量
Select count(*) from message_users where user_id = 1 and is_read is null
要计算收件箱中所有邮件的数量,我可以
Select count(*) from message_users where user_id = 1;
问题是如何在单个优化查询中结合两者?
答案 0 :(得分:2)
因此,您正在尝试实现满足一个条件的总行数以及满足额外条件的总行数:
|---------|---------|
| total | unread |
|---------|---------|
| 20 | 12 |
|---------|---------|
因此需要具有以下形式的表格:
SELECT A total, B unread FROM message_users WHERE user_id=1
A
非常简单,您已经或多或少地拥有它:COUNT(Id)
。
B
稍微复杂一些,可能采用SUM( IF(is_read IS NULL,1,0) )
形式 - 每次is_read不为null时加1;条件取决于您的数据库细节。
或B
可能如下:COUNT(CASE WHEN is_read IS NULL THEN 1 END) unread
- 这就是说'当is_read为空时,计算另一个1&#39 ;;条件取决于您的数据库细节。
总计:
SELECT COUNT(Id) total, COUNT(CASE WHEN is_read IS NULL THEN 1 END) unread FROM message_users WHERE user_id=1
或者:
SELECT COUNT(Id) total, SUM( IF(is_read IS NULL,1,0) ) unread FROM message_users WHERE user_id=1
就优化而言,我不知道可能比这更快的查询。 (如果确实存在,我很想知道它!)如果你遇到性能问题,可能有办法加快速度:
EXPLAIN
和一些阅读等。unread_messages
设置字段user
并直接获取此值。显然,需要进行一些写入失效,或者确实需要运行一些服务来保持这些值是最新的。有很多方法可以实现这一点,MySQL中的工具,自己动手等等。答案 1 :(得分:1)
在MySQL中,当你计算一个字段时,它只计算该字段的非空出现次数,所以你应该可以这样做:
SELECT COUNT(user_id), COUNT(user_id) - COUNT(is_read) AS unread
FROM message_users
WHERE user_id = 1;
未经测试,但它应该指向正确的方向。
答案 2 :(得分:1)
您可以将sum与CASE WHEN
子句一起使用。如果is_read
为空,则会将+1
添加到总和中,否则为+0
。
SELECT count(*),
SUM(CASE WHEN is_read IS NULL THEN 1 ELSE 0 END) AS count_unread
FROM message_users WHERE user_id = 1;