Hive表Distinct不同用法查询结果差异问题咨询
问题结论
你前两条查询里对DISTINCT的使用确实存在逻辑错误,三个查询结果不一致不是Hive执行bug,是不同SQL的实际执行逻辑完全不同,和你预期的逻辑不匹配。
三条SQL的实际执行逻辑拆解
select count(*) from test:直接统计test表的物理总行数,返回2609173是表的真实全量行数,这个结果本身没有问题。select distinct count(*) from test:这里的DISTINCT完全是冗余无效写法。SQL执行顺序是先做聚合计算:全表扫描算出count(*)的单个结果值2609173,生成只有1行1列的中间结果集,再对这个单值结果做去重,单值去重当然还是2609173。这条语句从头到尾没有对test表的原始数据行做任何去重操作。insert into testToo select distinct * from test:这才是真正对test表做全字段去重的逻辑——只要两行数据所有字段的值完全一致,就判定为重复,只保留1条写入testToo。最终插入673065行,说明原表260多万行里存在大量全字段完全重复的数据,整体重复率超过70%。
排查验证步骤
- 验证原表重复数据是否符合预期,执行分组统计SQL看重复分布:
执行后把-- 注意:低版本Hive不支持group by *,需要手动替换成test表的所有字段名 select repeat_cnt, count(*) as row_group_cnt from ( select *, count(*) as repeat_cnt from test group by 字段1,字段2,字段3 -- 替换为test表全部字段,和select *的列一一对应 ) t group by repeat_cnt order by repeat_cnt desc;repeat_cnt * row_group_cnt的结果累加,总和应该等于2609173,就能确认重复数据的判断完全正确。 - 匹配你的实际需求修正SQL写法:
- 如果要统计全字段去重后的总行数,不要写前两种错误写法,正确写法如下,执行结果应该和testToo的行数673065一致:
select count(*) from (select distinct * from test) t; - 如果只需要按某几个字段(比如主键)去重统计,不要用
distinct *,直接把去重字段放到count(distinct 字段名)里即可,比如按user_id去重统计用户数就写select count(distinct user_id) from test。
- 如果要统计全字段去重后的总行数,不要写前两种错误写法,正确写法如下,执行结果应该和testToo的行数673065一致:
- 验证插入结果正确性:执行
select count(*) from testToo确认行数确实为673065,排除testToo表提前存在历史数据、插入时字段映射错位的问题。
常见误区提醒
DISTINCT的作用范围是它后面紧跟的所有列的组合,且执行时机是在它所属的查询层级结果生成之后:如果写在聚合函数外层,只会对聚合完成后的结果去重,不会影响聚合前的原始行计算逻辑。
内容的提问来源于stack exchange,提问作者John Stud
相关产品推荐
相关产品推荐

