最近业务侧花样提需求,里面涉及到了各种数组的切片、合并、去重、拼接、压平等操作,本来以为需要自己开发很多udf才可以,后来扒了一下源码,发现这些用法sparksql已经帮我们实现了呀~~
太了不起了,我承认是我见识短了,所以就有了这篇......
总结一下sparksql(基于branch3.3) 中 array操作相关的骚气用法,这恐怕是总结的最全的一篇了,哈哈~~
从源码里看到,array相关函数主要分为四类:
-
array_funcs(一般的array函数,比如取最大、最小、包含、切片等)
-
collection_funcs(集合类的操作,比如数组求size、反转、拼接等)
-
map_funcs(从map结构中衍生出来的函数,比如element_at)
-
lambda_funcs(这几种函数中当属lambda_funcs最骚气,学起来会比较难,但可真是太灵活了,能帮我们解决很多实现上的问题)
需要注意的点:
-
1、array_funcs、collection_funcs、map_funcs都是支持全代码生成的,而lambda_funcs不支持全代码生成,所以在使用lambda_funcs时,需要注意效率问题
-
2、如果看功能描述看不太明白,可以多看看案例,一看案例就什么都明白了
-
3、在真正使用时,要测试一下对null的兼容性,有的函数对null做了兼容,有的函数没有做,使用前测一下最保险。对于遇到null会抛出异常的函数,我们需要对null提前做一下兼容处理
array_funcs
array
对应的类:CreateArray
功能描述:用sql创建一个数组(原来生成一个数组这么简单,我之前经常用split('1,2,3',',')这种形式来生成数组,现在看来用array函数最方便快捷)
版本:1.1.0
是否支持全代码生成:支持
用法:
--生成一维数组
select array(1, 3, 5) as arr;
+---------+
|arr |
+---------+
|[1, 3, 5]|
+---------+
--生成二维数组
select array(array(1, 2, 3), array(1, 3, 5)) as arr;
+----------------------+
|arr |
+----------------------+
|[[1, 2, 3], [1, 3, 5]]|
+----------------------+
array_contains
对应的类:ArrayContains
功能描述:判断数组是不是包含某个元素,如果包含返回true(这个比较常用)
版本:1.5.0
是否支持全代码生成:支持
用法:
--包含
select array_contains(array(1, 2, 3), 2) as is_contains;
+-----------+
|is_contains|
+-----------+
|true |
+-----------+
--不包含
select array_contains(array(1, 2, 3), 5) as is_contains;
+-----------+
|is_contains|
+-----------+
|false |
+-----------+
arrays_overlap
对应的类:ArraysOverlap
功能描述:
1、两个数组是否有非空元素重叠,如果有返回true
2、如果两个数组的元素都非空,且没有重叠,返回false
3、如果两个数组的元素有空,且没有非空元素重叠,返回null
版本:2.4.0
是否支持全代码生成:支持
用法:
--两个数组不存在null元素,且有重叠元素,返回true
select arrays_overlap(array(1, 2, 3), array(3, 4, 5)) as is_overlap;
+----------+
|is_overlap|
+----------+
|true |
+----------+
--两个数组其中有一个存在null元素,且有重叠元素,返回true
select arrays_overlap(array(1, 2, 3), array(null, 2, 6)) as is_overlap;
+----------+
|is_overlap|
+----------+
|true |
+----------+
--两个数组都存在null元素,且有重叠元素,返回true
select arrays_overlap(array(1, 2, null), array(null, 2, 6)) as is_overlap;
+----------+
|is_overlap|
+----------+
|true |
+----------+
--两个数组都不存在null元素,且无重叠元素,返回false
select arrays_overlap(array(1, 2, 3), array(4, 5, 6)) as is_overlap;
+----------+
|is_overlap|
+----------+
|false |
+----------+
--两个数组其中有一个存在null元素,且无重叠元素,返回null
select arrays_overlap(array(1, 2, 3), array(null, 5, 6)) as is_overlap;
+----------+
|is_overlap|
+----------+
|null |
+----------+
--两个数组都存在null元素,且无重叠元素,返回null
select arrays_overlap(array(1, 2, null), array(null, 5, 6)) as is_overlap;
+----------+
|is_overlap|
+----------+
|null |
+----------+
array_intersect
对应的类:ArrayIntersect
功能描述:返回两个数组相交的元素数组,并且不重复
版本:2.4.0
是否支持全代码生成:支持
用法:
--正常情况的案例
select array_intersect(array(1, 2, 3), array(1, 3, 5)) as intersect_arr;
+-------------+
|intersect_arr|
+-------------+
|[1, 3] |
+-------------+
--有重复且有null的案例
select array_intersect(array(1, 2, 3, 3, null), array(1, 3, 5, null)) as intersect_arr;
+-------------+
|intersect_arr|
+-------------+
|[1, 3, null] |
+-------------+
array_join
对应的类:ArrayJoin
功能描述:
用给定的分隔符和可选字符串替换null,来连接给定数组的元素;如果未设置【可选字符串替换null】,会过滤null值
从代码的构造函数也能看出,我们可以选择输入array(数组), delimiter(分隔符)这两个参数,也可以输入 array(数组), delimiter(分隔符),nullReplacement(如果数组中有null的,替换null的字符串,如果不输入,则默认把null过滤掉)这三个参数
版本:2.4.0
是否支持全代码生成:支持
用法:
--数组里没有null元素,且分隔符为逗号
select array_join(array('hello', 'world'), ',') as join_str;
+-----------+
|join_str |
+-----------+
|hello,world|
+-----------+
--数组里有null元素,且分隔符为逗号,且不输入【可选字符串替换null】,可以看到null元素被过滤
select array_join(array('hello', null ,'world'), ',') as join_str;
+-----------+
|join_str |
+-----------+
|hello,world|
+-----------+
--数组里有null元素,且分隔符为逗号,且将null替换为++
select array_join(array('hello', null ,'world'), ',', '++') as join_str;
+--------------+
|join_str |
+--------------+
|hello,++,world|
+--------------+
array_position
对应的类:ArrayPosition
功能描述: