MySQL带条件分组查询:仅保留RE计数为1的时间戳分组
要筛选出同一timestamp下robo='RE'的记录数恰好为1的分组,你可以通过分组后过滤(HAVING子句)+ 条件聚合来实现,以下是具体方案:
方案一:直接在分组后添加过滤条件
这是最简洁的写法,利用HAVING子句对分组结果进行筛选:
SELECT timestamp, MAX(robo) AS robo, -- 用MAX取分组中出现的robo值,符合你期望显示A的需求 COUNT(*) AS num_rows FROM tables GROUP BY timestamp HAVING SUM(CASE WHEN robo = 'RE' THEN 1 ELSE 0 END) = 1;
方案二:先用子查询统计再筛选(逻辑更清晰)
如果觉得直接写HAVING有点绕,可以先通过CTE(公共表表达式)计算每个timestamp的统计信息,再过滤:
WITH timestamp_stats AS ( SELECT timestamp, COUNT(*) AS num_rows, -- 统计当前timestamp下RE的记录数 SUM(CASE WHEN robo = 'RE' THEN 1 ELSE 0 END) AS re_count FROM tables GROUP BY timestamp ) SELECT timestamp, 'A' AS robo, -- 符合条件的分组中必然存在A,直接指定也可 num_rows FROM timestamp_stats WHERE re_count = 1;
关键逻辑解释
SUM(CASE WHEN robo = 'RE' THEN 1 ELSE 0 END):这个条件聚合是核心——它会遍历每个分组内的记录,遇到robo='RE'就计1,否则计0,求和后就是该timestamp下RE的总数量。HAVINGvsWHERE:WHERE是在分组前过滤行,而我们需要的是分组后对统计结果过滤,所以必须用HAVING子句。- 关于
robo字段的聚合:原查询中直接按timestamp分组却选择robo字段,在严格的SQL模式下会报错(因为robo不是分组键也没有聚合)。用MAX(robo)或ANY_VALUE(robo)(部分数据库支持)可以合法地获取分组中的一个robo值,符合你期望结果里显示A的要求。
补充:你的原始数据与查询对比
原始数据
第一组:
| timestamp | robo |
|---|---|
| 1518259341785 | A |
| 1518259341785 | A |
| 1518259341785 | A |
| 1518259341785 | RE |
第二组:
| timestamp | robo |
|---|---|
| 1518259341788 | RE |
| 1518259341788 | RE |
| 1518259341788 | RE |
| 1518259341788 | A |
原无条件查询结果
SELECT timestamp, robo, COUNT(*) AS num_rows FROM tables GROUP BY timestamp
| timestamp | robo | num_rows |
|---|---|---|
| 1518259341785 | A | 4 |
| 1518259341788 | A | 4 |
期望结果
| timestamp | robo | num_rows |
|---|---|---|
| 1518259341785 | A | 4 |
内容的提问来源于stack exchange,提问作者Saint Robson
相关产品推荐
相关产品推荐

