【问题标题】:Conditional count with group by in where clause在 where 子句中使用 group by 条件计数
【发布时间】:2015-05-16 11:04:05
【问题描述】:

我有一个简单的消息传递系统 - 将所有消息保存在一个表中。每条消息都可以(并且应该)与代表网站某些部分的其他 3 个表之一相关联。这是创建表语句

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,导致错误@987654329 @。

我正在尝试列出类似于 gmail 的消息 - 显示每个线程的总消息数 (t1_count, t2_count or t3_count),这就是我无法删除 OR from_user_id = 10 部分的原因。

为什么找不到该列以及如何应用该条件来显示仅接收(传出)的消息列表。

【问题讨论】:

  • inbox_count 是计算列,在 where 子句中不可用
  • 我们对“简单”的定义不同。这是糟糕的设计。
  • @Strawberry ))) 只是想说我没有任何嵌套线程/消息或连接到其他人的消息是回复。
  • @Strawberry,你能不能给我一个提示,它不会很糟糕。
  • 任何时候你枚举了列(n1,n2,n3...等 - 无论如何都在 n2 以上),警钟应该开始响起。

标签: mysql sql group-by


【解决方案1】:

除非我完全误解了你的意图......如果你想用inbox_count > 0 过滤,那么我想你想添加一个

HAVING COUNT(CASE WHEN to_user_id = 10 THEN 1 END) > 0

group by 子句之后。这将删除没有带有to_user = 10 的任何消息的“线程”。

See this fiddle 举例。

【讨论】:

  • @dav 其实你可以用HAVING inbox_count > 0代替case表达式,因为inbox_count是在解析have子句时定义的。
猜你喜欢
  • 2021-10-07
  • 2021-06-06
  • 2014-08-30
  • 2022-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多