视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Hive.GROUPINGSETS的“陷阱”
2020-11-09 15:11:44 责编:小采
文档


之前整理了一下Hive 0.10版引进的GROUPING SETS子句特性,并作了简单的句法使用体验和数据验证。但是当时没有注意到稍微复杂一点的情况,然后,在实际使用过程中,妥妥地就中了一。 这一发生在有JOIN操作的时候,情况是这样的:我要对Hive表data_table的

之前整理了一下Hive 0.10版引进的GROUPING SETS子句特性,并作了简单的句法使用体验和数据验证。但是当时没有注意到稍微复杂一点的情况,然后,在实际使用过程中,妥妥地就中了一。

这一发生在有JOIN操作的时候,情况是这样的:我要对Hive表data_table的a, b, c这3个字段去统计UV和VV这两个数据,并需要由c上卷到b,再上卷到a的统计数据。同时,要对字段b的值进行值映射,这是通过和另外一个专门描述b值的表进行JOIN来实现的。HQL语句如下:

select
 t1.a_desc,
 if(t1.group_bitvector= 1, '未区分', t2.b_desc) as b_desc,
 if(t1.group_bitvector= 1 or t1.group_bitvector = 3, '未区分', t1.c_desc) as c_desc,
 t1.group_bitvector,
 t1.act_uv,
 t1.act_vv
from
(
 select
 a_desc,
 b,
 c_desc,
 grouping__id as group_bitvector,
 count(distinctuer_ID) as act_uv,
 (sum(if(vv_ID is null, 1, 0)) + sum(if(vv_ID = "", 1, 0)) + count(distinct if(vv_ID is not null, if(vv_ID != "", vv_ID, null), null))) as act_vv
 from
 (
 select
 (
 case a
 when 0 then 'str_val_1'
 when 1 then 'str_val_2'
 when 2 then 'str_val_3'
 else 'str_val_4'
 end 
 )as a_desc,
 b,
 if(c= -2 or c = -1 or c = 9, 'c_desc1', 'c_desc2') as c_desc,
 uer_ID,
 vv_ID
 from data_table
 where a = xxx
 ) t
 group by a_desc, b, c_desc
 grouping sets (a_desc,(a_desc, b),(a_desc, b, c_desc))
) t1 join dim_table t2 on (t1.b = t2.b)

跑出来数据,晃眼一看,是正常的,仔细一看就经不起眼睛的考验了,group_bitvector这一列貌似缺了一个值,这样GROUPING SETS下来,group_bitvector应该出现1, 3, 7这三个值,但是出来的数据竟然没有1,也就是说,缺了最顶层的聚合(只对a进行求聚合)数据!

用力想了想,才拍脑袋发现了这个微妙的错误,JOIN君扔掉了一些数据!GROUPING SETS不是会把GROUP BY子句中没有参与聚合的列置为NULL么,这些NULL值在JOIN的时候就被无情地抛弃了。。这个时候,LEFT OUTER JOIN勇敢地站了出来,它说:只要用我替换原来的JOIN(内连接),就可以漂亮地消除了数据被过滤的问题:

select
 t1.a_desc,
 if(t1.group_bitvector= 1, '未区分', t2.b_desc) as b_desc,
 if(t1.group_bitvector= 1 or t1.group_bitvector = 3, '未区分', t1.c_desc) as c_desc,
 t1.group_bitvector,
 t1.act_uv,
 t1.act_vv
from
(
 select
 a_desc,
 b,
 c_desc,
 grouping__id as group_bitvector,
 count(distinctuer_ID) as act_uv,
 (sum(if(vv_ID is null, 1, 0)) + sum(if(vv_ID = "", 1, 0)) + count(distinct if(vv_ID is not null, if(vv_ID != "", vv_ID, null), null))) as act_vv
 from
 (
 select
 (
 case a
 when 0 then 'str_val_1'
 when 1 then 'str_val_2'
 when 2 then 'str_val_3'
 else 'str_val_4'
 end 
 )as a_desc,
 b,
 if(c= -2 or c = -1 or c = 9, 'c_desc1', 'c_desc2') as c_desc,
 uer_ID,
 vv_ID
 from data_table
 where a = xxx
 ) t
 group by a_desc, b, c_desc
 grouping sets (a_desc,(a_desc, b),(a_desc, b, c_desc))
) t1 left outer join dim_table t2 on (t1.b = t2.b)

这个场景中,grouping__id这个函数的用处也显现出来了,要是没有它,缺数据的问题更容易被忽视。。

最后,如果是多重或多列进行JOIN,就尤其要注意这个问题了~~~利用LEFT OUTER JOIN和GROUPING__ID的返回值,还是你能够很清晰无误地表达查询数据并进行GROUP组区分的需求。

最后的最后,还有一颗小小的地雷:gouping__id的返回值竟然是字符串类型,而不是直观上看到的整型!有时候Hive会自动为我们处理整型和字符串类型间的解析,毕竟字符串的很多运算和整型运算很相似。但有时候Hive也不会给我们处理,比如在用case…when…then…end子句的时候,字段数据类型必须严格相同,否则会报错,——虽然这个错误提示很明显,比较容易排查。

下载本文
显示全文
专题