Spark SQL/Hive中如何剔除同start_dt下形成循环的重复记录?
解决Spark SQL/Hive中循环记录去重问题
这个场景我太熟悉了!要解决同start_dt下的循环记录仅保留一条的问题,核心思路是先把互为循环的配对(比如A-B和B-A)归为同一组,然后每组只取任意一条即可。下面给你两种在Spark SQL/Hive里都能用的实用方案:
方法1:窗口函数分组筛选
通过生成一个不区分prv和cur顺序的分组标识,再用窗口函数给每组记录编号,最后只保留每组的第一条:
WITH ranked_records AS ( SELECT *, -- 用LEAST和GREATEST生成统一分组键,A-B和B-A会得到相同的组合 ROW_NUMBER() OVER ( PARTITION BY start_dt, LEAST(prv, cur), GREATEST(prv, cur) ORDER BY prv -- 排序字段可随意指定,因为只需要保留一条 ) AS row_num FROM your_input_table ) SELECT prv, cur, start_dt FROM ranked_records WHERE row_num = 1;
逻辑说明:
LEAST(prv, cur)会返回两个值中较小的那个,GREATEST(prv, cur)返回较大的那个,这样A-B和B-A的分组键完全一致- 按
start_dt+分组键分区后,用ROW_NUMBER()给每条记录编号,取row_num=1就实现了每组仅留一条
方法2:GROUP BY聚合取固定值
如果除了prv和cur外其他字段都相同,也可以直接通过分组聚合来得到结果,写法更简洁:
SELECT MIN(prv) AS prv, MAX(cur) AS cur, start_dt FROM your_input_table GROUP BY start_dt, LEAST(prv, cur), GREATEST(prv, cur);
逻辑说明:
- 同样用
LEAST和GREATEST做分组键,把循环配对归为一组 - 因为每组只有两种可能的记录(A-B或B-A),用
MIN(prv)会取到字典序更小的那个值,MAX(cur)取到更大的那个,刚好匹配你示例里的输出格式;如果想保留另一组(比如B-A),换成MAX(prv)和MIN(cur)就行
两种方法都能完美匹配你的输入输出需求,根据自己的习惯选就行~
内容的提问来源于stack exchange,提问作者user2895589
相关产品推荐
相关产品推荐

