工作中使用多维度分组时并不想写一大堆union all,为了便于代码简洁喜欢使用grouping_id这个函数,使用久了会发现hive_1.2.1版本以前的grouping_id计算方式和以后的计算方式会有所不同步。这样造成使用这个函数的时候如果存在历史数据使用时存在着矛盾,这时很多聪明人会想到的解决办法就是把不同的grouping_ID产生的数据按照时间分段开来重新计算,这样会造成许多大量重复的代码。在没有想到下面这个解决方案时,那种根据不同时间段groupingID 分段计算是一种解决方案但不是最佳方案。以下介绍一种最佳解决方案。
1.groupingID的计算方式,分新旧俩个版本

GROUP BY a,b,c,d,e
 GROUPING SETS ( (a,b,c,d,e) 11111 GROUPING_ID=32 | 00000 GROUPING_ID=0 hive_1.2._1
 ,(a,b,d,e) 11011 GROUPING_ID=27 | 00100 GROUPING_ID=4 hive_1.2._1
 ,(a,c,d,e) 11101 GROUPING_ID=29 | 01000 GROUPING_ID=8 hive_1.2._1
 ,() 00000 GROUPING_ID=0 | 11111 GROUPING_ID=32 hive_1.2._1
 )


由此上图可见按|分割是新旧版本hive的groupingID计算方式,举例说明GROUP BY a,b,c,d,e是五个维度,那么我们计算其中一组分组GROUPING SETS(b,c,d,e)。旧版本计算方式,假设五个维度都在则是11111.现在我们可以看到这一组中缺少了一个a。则我们可以把111111看作是默认的edcba对应的位置出现就是1。现在分组(b,c,d,e)缺少了a,则将a位置的1置为0.其结果是11110.对应的十进制GROUPING_ID=30.
而 hive_1.2._1及以后的版本计算方式还是一样取默认分组00000(abcde),那个位置出现位置就是0,所有是00000.同样计算新版本分组GROUPING SETS (b,c,d,e) 对应占位的不出现是1出现是0的二进制数是10000,十进制GROUPING_ID=16。
搞清楚了不同版本之间的groupingID的计算方式,现在我们可以通过一个计算方式寻求解决方案。通过老旧版本的groupID通过以下方式进行转换***conv(reverse(substr(bin(~CAST(GROUPING_ID AS BIGINT)),(-1)5)),2,10)**,解释以下公式,现将新版本groupingID的十进制位取反,假设groupingID是10,这取反后是-11.再将-11转成bin二进制数01011,截取完成后用函数conv将二进制转成10进制。即完成转换。
通常我们通过sql语句中使用如下字段转换完成IF(’$GROUPING_SETS_BACKWARD_CAMPATIBLITY’=‘true’,conv(reverse(substr(bin(~CAST(GROUPING_ID AS BIGINT)),(-1)*5)),2,10),GROUPING_ID) AS GROUPING_ID

以上即为新旧hive版本中grouping_id计算方式不同造成的差异化解决方案,欢迎指正。