为何子查询新增列后Sum()结果增大?该如何解决?
问题分析与解决
两段SQL脚本及执行结果
脚本1
select year, sum(traffic) from ( select year, count(distinct id) traffic from table.name where clean_url like "%.com/blog/%" group by 1 ) GROUP BY 1
执行结果:3078347
脚本2
select year, sum(traffic) from ( select year, month, count(distinct id) traffic from table.name where clean_url like "%.com/blog/%" group by 1,2 ) GROUP BY 1
执行结果:3149904
问题解答
1. 结果差异的原因
核心原因是同一个用户(id)可能在同一年的多个月份都有符合条件的访问行为:
- 脚本1直接按
year分组,用count(distinct id)统计的是全年范围内的独立用户数——不管用户当年访问多少次、覆盖多少个月,每个用户都只被统计1次。 - 脚本2先按
year+month分组,每个月内统计该月的独立用户数,再将各月的统计值相加。如果一个用户在多个月份都访问过,就会在每个对应月份的分组里被各算1次,最终sum的结果会把这个用户重复统计,导致总和远大于脚本1的结果。
2. 解决方案(针对新增16个字段后结果虚高的问题)
首先要明确你的业务需求:是要各细分维度(含16个字段)下的独立用户数,还是要按年统计的全年独立用户总数?不同需求对应不同的解决方式:
需求A:按年统计全年独立用户总数,同时保留16个字段的维度查看
这种情况不能用「先分组count再sum」的逻辑,要确保每个用户在全年内只被统计一次。可以通过标记用户的首次访问维度实现:
select year, -- 这里加上需要的16个新增字段 count(distinct id) as traffic from ( select id, year, -- 同步加上16个新增字段 row_number() over(partition by id order by visit_date) as rn from table.name where clean_url like "%.com/blog/%" ) t where rn = 1 -- 只取用户首次访问对应的维度记录 group by year, -- 同步加上16个新增字段
这样每个用户只会在首次访问的维度分组里被统计一次,后续按year汇总的结果会和脚本1的准确值一致。
需求B:统计各细分维度(含16个字段)下的独立用户数
这种情况下,sum结果大于年总用户数是正常现象——因为同一个用户可能出现在多个维度分组中(比如同一用户在不同月份、不同字段值下都有访问)。如果业务就是需要统计每个分组的独立用户数,那当前的逻辑是正确的,无需修改;如果是误将「分组用户数之和」等同于「年总用户数」,那需要调整需求认知,两者本身就不是同一个指标。
内容的提问来源于stack exchange,提问作者DoggedFox
相关产品推荐
相关产品推荐

