0 需求
hive中怎么统计array中非零的个数
【0,1,3,6,0】
结果:非0的个数为3
1 实现
(1)将array转换成字符串,采用concat_ws()函数
select concat_ws(',',array) from test_array
返回:0,1,3,6,0
注意区分concat函数和concat_ws函数
- concat函数在连接字符串的时候,只要其中一个是NULL,那么将返回NULL
- concat_ws函数在连接字符串的时候,只要有一个字符串不是NULL,就不会返回NULL。
hive> select concat('a','b');
OK
ab
Time taken: 0.477 seconds, Fetched: 1 row(s)
hive> select concat('a','b',null);
OK
NULL
Time taken: 0.181 seconds, Fetched: 1 row(s)
hive> select concat_ws('-','a','b');
OK
a-b
Time taken: 0.245 seconds, Fetched: 1 row(s)
hive> select concat_ws('-','a','b',null);
OK
a-b
Time taken: 0.177 seconds, Fetched: 1 row(s)
hive> select concat_ws('','a','b',null);
OK
ab
Time taken: 0.184 seconds, Fetched: 1 row(s)
(2) 使用regexp_replace()函数将0值替换成''或null
select regexp_replace("0,1,3,6,0",'0','null')
+------------------+--+
| _c0 |
+------------------+--+
| null,1,3,6,null |
+------------------+--+
注意此处null需要引号引起来,因为是串。不引起来则是如下结果
select regexp_replace("0,1,3,6,0",'0',null)
+-------+--+
| _c0 |
+-------+--+
| NULL |
+-------+--+
(3)解析字符串,求其非0个数。注意这里不能用length(),length()是求字符串的长度,上述结果用length()求出返回结果是15,因为length()会对每个字符进行计算。
select length(regexp_replace("0,1,3,6,0",'0','null'))
+------+--+
| _c0 |
+------+--+ null:4
| 15 |
+------+--+
我们需要对字符串解析split()返回一个数组,计算数组大小。数组大小用size()函数会忽略null或''的统计
0: jdbc:hive2://10.9.4.117:10000> select size(split(regexp_replace("0,1,3,6,0",'0',''),','));
+------+--+
| _c0 |
+------+--+
| 5 |
+------+--+
1 row selected (0.309 seconds)
0: jdbc:hive2://10.9.4.117:10000> select size(split(regexp_replace("0,1,3,6,0",'0','null'),','));
+------+--+
| _c0 |
+------+--+
| 5 |
+------+--+
1 row selected (0.147 seconds)
(4)最终SQL如下
select size(split(regexp_replace(array_str,'0',''),',')) as cnt
from(
select concat_ws(',',array) array_str from test_array) t
2 小结
- (1)数组转字符串的方法
- (2)字符串的正则匹配(非0值统计技巧)
- (3)字符串的解析,split()转换成数组,size()统计点位个数。