1. 概述 数组(Array)是有序的元素序列,组成数组的各个变量称为数组的元素。数组是在程序设计中,为了处理方便把具有相同类型的若干元素按有序的形式组织起来的一种形式。按数组元素的类型不同,数组又可分为数值数组、字符数组等各种类别。数组在各个编程语言里处理方式不同,本文仅列出数组在Spark SQL里的函数用法。 特点 - 数组是相同数据类型的元素的集合。
- 数组中的各元素的存储是有先后顺序的,它们在内存中按照这个先后顺序连续存放在一起。
- 数组元素用整个数组的名字和它自己在数组中的顺序位置(索引)来查询。
- 数组在数据库里展示为整体用方括号括起来的类字符串,每个元素用逗号隔开。例如 [1, 2, 3]。
2. 函数列表2.1. 数组创建与转换用途 | 函数 | 示例 | 结果 | 将分组后的数据收集到一个列表中,返回不去重的数组 | collect_list(expr); array_agg(expr) | collect_list([字段]) [字段]值分别为 A,A,B,B,C,D | [A,A,B,B,C,D] | 将分组后的数据收集到一个列表中,返回去重的数组 | collect_set(expr) | collect_set([字段]) [字段]值分别为 A,A,B,B,C,D | [A,B,C,D] | 将多列值合并为一个数组 | array(expr, ...) | array(1, 2, 3) | [1,2,3] | 根据指定的分隔符将字符串拆分成数组。 | split(str, regex[, limit]) limit限制拆分元素数,可省略 | split('A-B-C', '-'); split('A-B-C', '-',2) | [A,B,C]; [A,B-C] | 将字符串拆分成句子,并将每个句子中的单词提取到数组里。 | sentences(str[, lang, country]) | sentences('Hi there! Good morning.') | [["Hi","there"],["Good","morning"]] | 生成按固定步长递增的序列数组,用于数值和日期时间类型 | sequence(start, stop, step) | sequence(1, 5); sequence(to_date('2021-01-01'), to_date('2021-03-01'), interval 1 month) | [1,2,3,4,5]; [2021-01-01,2021-02-01,2021-03-01] | 创建一个包含重复元素的数组 | array_repeat(element, count) | array_repeat('123', 2) | ["123","123"] | 数组拆分为多行,每个元素一行 | explode(expr) | explode(array('A','B')) | A B | 把数组里元素用分隔符拼接为字符串 | array_join(array, sep[, nullRep]) nullRep用来指定null值的替换值,省略时移除null | array_join(array('hello', null ,'world'), ' ', ',') | hello , world | concat_ws(sep[, str | array(str)]+) 移除null | concat_ws(',',array('hello', null ,'world')) | hello,world |
2.2. 数组内数据处理用途 | 函数 | 示例
| 结果 | 向数组尾部追加元素 | array_append(array, element) | array_append(array('b', 'd', 'c', 'a'), 'd') | ["b","d","c","a","d"] | 向数组指定位置插入元素 | array_insert(x, pos, val) pos从1开始,负数代表倒数位置 | array_insert(array(5, 3, 2, 1), -4, 4) | [5,4,3,2,1] | 对数组元素进行去重 | array_distinct(array) | array_distinct(array(1, 2, 3, null, 3)) | [1,2,3,null] | 移除数组里所有的某指定元素 | array_remove(array, element) null不能移除 | array_remove(array(1, 2, 3, null, 3), 3) | [1,2,null] | 移除数组里所有null | array_compact(array) | array_compact(array(1, 2, 3, null, 3)) | [1,2,3,3] | 将数组翻转排序 | reverse(array) | reverse(array(2, 1, 4, 3)) | [3,4,1,2] | 对数组随机排序 | shuffle(array) | shuffle(array(1, 20, 3, 5)) | [3,1,5,20] | 数组排序 | array_sort(expr[, func]) func指定排序方式,省略时升序, null排最后 | array_sort(array('b', 'd', null, 'c', 'a')) | ["a","b","c","d",null] | sort_array(array[, true/false]) 升序(true)时null排前面,降序(false)时null排最后 | sort_array(array('b', 'd', null, 'c', 'a'), true) | [null,"a","b","c","d"] | 从固定位置截取固定长度的子数组 | slice(x, start, length) | slice(array(1, 2, 3, 4), 2, 2) | [2,3] |
2.3. 数组查询与计算用途 | 函数 | 示例
| 结果 | 数组长度(元素个数) | size(expr) ; array_size(expr) | size(array('b', 'd', 'c', 'a')) | 4 | 数组里最大值 | array_max(array) | array_max(array(1, 20, null, 3)) | 20 | 数组里最小值 | array_min(array) | array_max(array(1, 20, null, 4)) | 1 | 查询元素在数组里的位置 | array_position(array, element) | array_position(array('A','B','C'), B) | 2 | 提取指定位置的元素 | element_at(array, n) n从1开始,为负数时从后往前查询 | element_at(array('A','B','C'), -1) | C | get(array, index) index从0开始 | get(array(1, 2, 3), 0) | 1 | array[n] n从0开始,不能为负 | array('A','B','C')[0] | A | 检查数组里是否包含指定元素,返回true/false | array_contains(array, value) | array_contains(array(1, 2, 3), 2) | true | 检查数组里是否存在满足特定条件的元素,返回true/false | exists(array, pred) | exists(array(1, 2, 3), x -> x % 2 == 0) | true | 检查数组里所有元素是否都满足特定条件,返回true/false | forall(array, pred) | forall(array(1, 2, 3), x -> x % 2 == 0) | false | 把数组内元素按照二元运算聚合为一个结果值 | aggregate(array, start, merge, finish); reduce(array, start, merge, finish) | aggregate(array(1, 2, 3), 0, (acc, x) -> acc + x) 数组内元素求和 | 6 | 筛选符合特定条件的元素,返回新的数组 | filter(array, func) | filter(array(1, 2, 3), x -> x % 2 == 1) | [1,3] | 按照指定方法逐元素转换,返回新的数组 | transform(array, func) | transform(array(1, 2, 3), x -> x + 1) | [2,3,4] | 对数组内数值求和(*自定义函数) | array_sum(array) | array_sum(array(1, 2, 3)) | 6 |
2.4. 多数组处理用途 | 函数 | 示例 | 结果 | 拼接数组,元素不去重 | expr1 || expr2 | array(1, 2, 3) || array(4, 5) | [1,2,3,4,5] | concat(col1, col2, ..., colN) | concat(array(1, 2, 3), array(4, 5)) | 返回存在于array1,但不存在于array2里的元素列表,元素去重 | array_except(array1, array2) | array_except(array(1, 2, 3), array(1, 3, 5)) | [2] | 返回两个数组的交集,元素去重 | array_intersect(array1, array2) | array_intersect(array(1, 2, 3), array(1, 3, 5)) | [1,3] | 返回两个数组的并集,元素去重 | array_union(array1, array2) | array_union(array(1, 2, 3), array(1, 3, 5)) | [1,2,3,5] | 检查两个数组是否存在非null值的交集,返回true/false | arrays_overlap(array1, array2) | arrays_overlap(array(1, 2, 3), array(3, 4, 5)) | true | 把二维数组合并为一维数组 | flatten(arrayOfArrays) | flatten(array(array(1, 2), array(3, 4))) | [1,2,3,4] |
3. 注意事项: 观远BI前端不直接支持数组类型,字段类型会显示为“文本”,但是不代表可以完全当做文本来使用。例如用文本的筛选方式“包含”、“以...开头”等方式来筛选数组字段会报错。一般情况下,建议尽量在ETL里用函数把数组类型字段转换成文本后再输出用于卡片报表制作。 |