在SQL中,去重计数一般都是用count(distinct column)来执行;
而在累计去重计数的场景下,大家就会直接想到,用窗口函数over(partition by column)来进行操作;
在实际Impala的测试过程中,count(distinct columnA) over(partiton by columnB)是不被支持的语法;那么就需要另辟蹊径,思考其他解决方案,结合其他函数,完成累计去重计数,尽量满足分析需求;
这里示例的解决方案,是使用row_number() 与 decode() 结合,实现累计去重计算;
语法说明:
row_number(),窗口函数中常用的功能,根据排序依据,编排序号
decode(),decode(columnA,"若字段值为A","则显示1","否则显示0")
此处示例一个分析场景:
根据加班管理需要,计算每天累计有多少名员工加班了,需要去重计数
那么按照上述的解决方案,这边提供的Impala环境下的实现思路如下:
① 读取员工加班记录表,按员工进行分区,按加班日期进行排序,保证每个员工只有一条序号=1的记录
② 根据①的结果,按加班日期进行分区,只求和序号为1的数据,其他数据均处理为0,不做求和
③ 按照上述步骤,先保证每个员工只有一条记录的序号为1,再进行序号为1的数据求和,即可以实现对加班数据,进行计算每天累计有多少名员工加班
实际Impala的查询参考如下:
select over_date,
sum(decode(rowid,1,1,0)) over(partition by over_date) dis_count
-- sum(if(rowid=1,1,0)) over(partition by over_date) dis_count
from
(select code,over_date,
row_number() over(partition by code order by over_date) rowid
from over_list_table
) sou
通过以上方式,通过巧妙使用row_number下每个分区下只会有一个1的特点,就可以在Impala中实现累计去重计算,希望可以帮助大家
上述方式在数据量大时,也是牺牲了一点性能的,如果大家有更好的方案,欢迎评论分享