ClickHouse聚合查询如何让IN条件中不存在的code返回计数0
ClickHouse 指定枚举值聚合补0实现方案
该需求可直接实现。
原查询无法返回CCCC对应0值,核心原因是WHERE code IN ('AAAA','CCCC')只会筛选原表中已存在的code,不存在的code不会进入分组计算环节,自然不会出现在结果中。
实现核心逻辑:先构造包含所有待查询code的虚拟基准表,再通过左连接关联原表数据,最后完成聚合统计,常用写法有两种:
方法1:用 arrayJoin 快速构造枚举值列表
适合code列表不长、直接写在查询里的场景,写法最简洁:
SELECT target.code, count(src.value) AS count FROM (SELECT arrayJoin(['AAAA', 'CCCC']) AS code) AS target LEFT JOIN your_table AS src ON target.code = src.code GROUP BY target.code
注意:这里必须用
count(原表字段)不能用count(*)。左连接后匹配不到原表数据的行,原表字段值为NULL,count(字段)会自动忽略NULL值,匹配不到的code统计结果自然为0;如果用count(*)会把空行统计为1,结果错误。
执行后返回的结果正好符合预期:
code | count ------------ AAAA | 2 CCCC | 0
方法2:用 VALUES 构造常量虚拟表
适合code列表较长、或者需要明确指定字段类型的场景:
SELECT target.code, count(src.value) AS count FROM (VALUES('code', String, 'AAAA', 'CCCC')) AS target LEFT JOIN your_table AS src ON target.code = src.code GROUP BY target.code
额外注意事项
如果需要对原表加额外过滤条件,不要直接在最外层WHERE里写,否则会把左连接生成的空行过滤掉,导致补0失效。正确做法是先把原表过滤完成做成子查询,再和基准code表做左连接:
比如要统计value大于10的计数,正确写法如下:
SELECT target.code, count(filtered_src.value) AS count FROM (SELECT arrayJoin(['AAAA', 'CCCC']) AS code) AS target LEFT JOIN (SELECT code, value FROM your_table WHERE value > 10) AS filtered_src ON target.code = filtered_src.code GROUP BY target.code
该语句返回结果为:
code | count ------------ AAAA | 1 CCCC | 0
内容的提问来源于stack exchange,提问作者Альберт Александров
相关产品推荐
相关产品推荐

