在 where 子句中使用 group by 进行条件计数
Conditional count with group by in where clause
我有一个简单的消息系统 - 将所有消息保存在一个 table 中。每条消息都可以(并且应该)与代表网站某些部分的其他 3 个 table 之一相关联。这是创建 table 语句
CREATE TABLE `messages` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`from_user_id` int(11) DEFAULT NULL,
`to_user_id` int(11) DEFAULT NULL,
`message` text COLLATE utf8_bin,
`table1_id` int(11) DEFAULT NULL,
`table2_id` int(11) DEFAULT NULL,
`table3_id` int(11) DEFAULT NULL,
`is_unread` tinyint(1) DEFAULT NULL,
`date` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
对于每条消息,从 table1_id, table2_id and table3_id
如果某列有值,则意味着其余 2 列为空。这是 sqlfiddle 结构和示例数据:http://sqlfiddle.com/#!9/b98a2/1/0.
所以,table1_id, table2_id and table3_id
是一种线程,我在分组时使用它来显示消息列表。这是我的查询
SELECT
id,
table1_id,
table2_id,
table3_id,
message,
from_user_id,
to_user_id,
COUNT(table1_id) AS t1_count,
COUNT(table2_id) AS t2_count,
COUNT(table3_id) AS t3_count,
MAX(CASE WHEN to_user_id = 10 AND is_unread = 1 THEN 1 END) AS is_unread,
COUNT(CASE WHEN to_user_id = 10 THEN 1 END) AS inbox_count
FROM
messages
WHERE to_user_id = 10 OR from_user_id = 10
GROUP BY table1_id,
table2_id,
table3_id
ORDER BY id DESC
这是在 sqlfiddle http://sqlfiddle.com/#!9/b98a2/2/0
当我必须显示所有消息时,此查询工作正常,但如果我只想显示 id = 10
用户的收件箱 我必须检查每个线程至少收到一条消息的条件,因此我尝试应用条件 AND inbox_count > 0
,结果一个错误 Unknown column 'inbox_count' in 'where clause'
。
我正在尝试列出类似于 gmail 的邮件 - 显示每个线程的邮件总数 (t1_count, t2_count or t3_count
),这就是我无法删除 OR from_user_id = 10
部分的原因。
为什么找不到该列以及我如何应用该条件来显示仅接收(传出)消息的列表。
除非我完全误解了你的意图...如果你想用 inbox_count > 0
过滤那么我想你想添加一个
HAVING COUNT(CASE WHEN to_user_id = 10 THEN 1 END) > 0
在 group by
子句之后。这将删除没有任何消息的 "threads" to_user = 10
.
See this fiddle 举个例子。
我有一个简单的消息系统 - 将所有消息保存在一个 table 中。每条消息都可以(并且应该)与代表网站某些部分的其他 3 个 table 之一相关联。这是创建 table 语句
CREATE TABLE `messages` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`from_user_id` int(11) DEFAULT NULL,
`to_user_id` int(11) DEFAULT NULL,
`message` text COLLATE utf8_bin,
`table1_id` int(11) DEFAULT NULL,
`table2_id` int(11) DEFAULT NULL,
`table3_id` int(11) DEFAULT NULL,
`is_unread` tinyint(1) DEFAULT NULL,
`date` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
对于每条消息,从 table1_id, table2_id and table3_id
如果某列有值,则意味着其余 2 列为空。这是 sqlfiddle 结构和示例数据:http://sqlfiddle.com/#!9/b98a2/1/0.
所以,table1_id, table2_id and table3_id
是一种线程,我在分组时使用它来显示消息列表。这是我的查询
SELECT
id,
table1_id,
table2_id,
table3_id,
message,
from_user_id,
to_user_id,
COUNT(table1_id) AS t1_count,
COUNT(table2_id) AS t2_count,
COUNT(table3_id) AS t3_count,
MAX(CASE WHEN to_user_id = 10 AND is_unread = 1 THEN 1 END) AS is_unread,
COUNT(CASE WHEN to_user_id = 10 THEN 1 END) AS inbox_count
FROM
messages
WHERE to_user_id = 10 OR from_user_id = 10
GROUP BY table1_id,
table2_id,
table3_id
ORDER BY id DESC
这是在 sqlfiddle http://sqlfiddle.com/#!9/b98a2/2/0
当我必须显示所有消息时,此查询工作正常,但如果我只想显示 id = 10
用户的收件箱 我必须检查每个线程至少收到一条消息的条件,因此我尝试应用条件 AND inbox_count > 0
,结果一个错误 Unknown column 'inbox_count' in 'where clause'
。
我正在尝试列出类似于 gmail 的邮件 - 显示每个线程的邮件总数 (t1_count, t2_count or t3_count
),这就是我无法删除 OR from_user_id = 10
部分的原因。
为什么找不到该列以及我如何应用该条件来显示仅接收(传出)消息的列表。
除非我完全误解了你的意图...如果你想用 inbox_count > 0
过滤那么我想你想添加一个
HAVING COUNT(CASE WHEN to_user_id = 10 THEN 1 END) > 0
在 group by
子句之后。这将删除没有任何消息的 "threads" to_user = 10
.
See this fiddle 举个例子。