Hive高频函数(二)

简介: Hive高频函数(二)

前言

hive中有很大部分的函数是基于复杂类型去计算的,因为我们现实中的数据往往不是f(x)->y这种类型的,更多其实是f(x1,x2,x3)->y的类型。在这种场景下,hive提供了复杂类型的操作。数据的结构类型会决定udf作用的目标也不一样,这种场景下的udf往往会通过多步组合来得到我们想要的结果。

hive中的复杂类型盘点

类型 说明
ARRAY 包含同类型元素的数组,索引从0开始 ARRAY
MAP 字典 MAP<primitive_type, data_type>
STRUCT 结构体 STRUCT<col_name : data_type [COMMENT col_comment], …>
UNIONTYP 联合体 UNIONTYPE<data_type, data_type, …>

这些数据类型同样提供了udf来生成,我们可以在源码中找到这部分:

    system.registerGenericUDF("array", GenericUDFArray.class);
    system.registerGenericUDF("assert_true", GenericUDFAssertTrue.class);
    system.registerGenericUDF("map", GenericUDFMap.class);
    system.registerGenericUDF("struct", GenericUDFStruct.class);
    system.registerGenericUDF("named_struct", GenericUDFNamedStruct.class);
    system.registerGenericUDF("create_union", GenericUDFUnion.class);
    system.registerGenericUDF("extract_union", GenericUDFExtractUnion.class);

常用UDF盘点

有了之前的准备,我们可以开始我们的udf解释了:

集合处理类函数

array

这个函数就是生成我们一个数组类型的结果:

select array('facebook', 'com','a') as url;
["facebook","com","a"]

需要注意显示的时候其实是会带有[]的字样

sort_array

这个函数其实是对我们的数组类似的结果进行排序,所以这个函数需要传入数组

select sort_array(array('facebook', 'com','a')) as url;
["a","com","facebook"]

用数字会更加明显一些:

select sort_array(array(1,3,6,5,8,9)) as url;
[1,3,5,6,8,9]

map

map对应的数据格式就是(k,v)的结构,我们用这个函数去构造map类型的数据对象:

select map("1","宋江","2","林冲")
{"1":"宋江","2":"林冲"}

聚合类函数

聚合函数需要作用在一个group的数据组中,对group by之后的结果进行处理,为了说明问题,我需要准备点数据,

表的结构情况:

desc temp.test_tab;
num                     int                                         
a                       string                                      
g1                      string 

表数据如下:

select * from temp.test_tab;
1       A       g
2       B       g
3       C       g
4       C       g
4       NULL    g

group_concat

函数说明:group_concat(col1, isUnique) - Aggregation function, collect all non-null col1 value into an array, if isUnique is non-zero, remove the duplicated values.

采集所有非空的列上面的值到一个数组中,isUnique如果非0,则会去掉重复的值。

我们先参数传0

select g1,group_concat(a,0) from temp.test_tab group by g1
g       ["A","B","C","C"]

再来一波非0的

select g1,group_concat(a,1) from temp.test_tab group  by g1;
g       ["A","B","C"]

collect_list

函数说明:Returns a list of objects with duplicates

这个函数其实就是返回数据聚合之后的数组对象,这里特别强调了一下会带重复

select g1,collect_list(a) from temp.test_tab group  by g1
g       ["A","B","C","C"]

collect_set

函数说明:Returns a set of objects with duplicate elements eliminated

这个函数和上面的函数想呼应,只不过结果会去重

select g1,collect_set(a) from temp.test_tab group  by g1;
g       ["A","B","C"]

需要说明的是,这样子返回去重的数据是不保证顺序的,实际情况我们需要顺序的时候会配合sort_array函数一起使用:

select g1,sort_array(collect_set(num)) from temp.test_tab group  by g1
g       [1,2,3,4]

concat_ws

这个函数在之前也有聊过,事实上,这个函数传入的类型可以是数组和简单类型的组合,放在这里说的原因是这个函数往往和上面的聚合函数进行组合

select concat_ws('.', 'www', array('facebook', 'com'))  as url;
www.facebook.com

因为可以传入数组,所以我们实际使用的时候会用把这个函数套上去,得到我们要的结果:

select g1,concat_ws(',',collect_list(a)) from temp.test_tab group  by g1
g       A,B,C,C

这次的变化在于,返回的结果已经是一个字符串类型了

转置类操作

explode

这个函数就是把横着的扳直,作用在map结构和list结构上

select explode(array(1,3,6,5,8,9)) as id 

id
1
3
6
5
8
9

map类型输出的列名就是key和value

select explode(map("1","宋江","2","林冲"))
key   value 
1       宋江
2       林冲

lateral view

这个其实是一个操作,因为基于explode操作之后,我们的表数据会被硬生生一行变成多行了,这个和原有的数据需要有一个对应的关系

比如我们之前的sql:

select g1,sort_array(collect_set(num)) as id from temp.test_tab group  by g1

这个生成的结果就是:

g [1,2,3,4]

但是我们如果进行explode:

select g1,explode(sort_array(collect_set(num))) as id from temp.test_tab group  by g1
• 1

这个操作其实就是类似两张表去做join操作了,类似这样:

g [1,2,3,4]  => 要变成
g  1
g  2 
g  3 
g  4

这种情况的话在sql运算中其实没有做子查询的时候是不能实现的,这个时候就做了一个破坏了数据操作范式的语法lateral,把explode运算的结果,和原有的数据做一次类似join的操作,我们可以看下源码上对这一操作的描述:

The lateral view join operator is used for FROM src LATERAL VIEW udtf()...
 * This operator was implemented with the following operator DAG in mind.
 * 
 *            [Table Scan]
 *                |
 *       [Lateral View Forward]
 *              /   \
 *   [Select](*)    [Select](adid_list)
 *            |      |
 *            |     [UDTF] (explode)
 *            \     /
 *      [Lateral View Join]
 *               |
 *               |
 *      [Select] (pageid, adid.*)
 *               |
 *              ....

later view 在实际操作中是做了一次later view join的操作,结果集就会达到join的效果,举例说明:

select num,id from temp.test_tab lateral  view explode(array(1,3))q  as  id;
• 1

注意id的列名的来自后面生成的as id列,我们看图中的结果数据,每一个num值都和新的1 3关联上了,这个其实数据量也翻了两倍了

这个函数除了在把数据拉直的时候处理之外,还有个场景是把join两边数据不均匀的时候提前做分组,这样子可以避免数据倾斜。

目录
相关文章
|
1月前
|
SQL HIVE
Hive LAG函数分析
Hive LAG函数分析
45 0
|
1月前
|
SQL JSON Java
Hive【Hive(四)函数-单行函数】
Hive【Hive(四)函数-单行函数】
|
28天前
|
SQL HIVE
hive高频函数(一)
hive高频函数(一)
21 0
|
1月前
|
SQL 分布式计算 HIVE
Hive Cli / HiveServer2 中使用 dayofweek 函数引发的BUG!
在Hive 3.1.2和Spark 3.0.2集群环境中,遇到`dayofweek`函数bug。当`create_date`为字符串类型时,`dayofweek`函数结果错位。修复方法是将`create_date`转换为`date`类型。在Spark SQL中,原始代码能正常运行,未出现此问题。因此建议在Hive中使用转换后的日期类型以避免错误。
|
1月前
|
SQL XML JSON
Hive函数全解——思维导图 + 七种函数类型
Hive函数全解——思维导图 + 七种函数类型
41 2
Hive函数全解——思维导图 + 七种函数类型
|
1月前
|
SQL HIVE
【Hive SQL】字符串操作函数你真的会用吗?
本文介绍了SQL中判断字符串是否包含子串的几种方法。`IN`函数判断元素是否完全等于给定元素组中的某项,而非包含关系。`INSTR`和`LOCATE`函数返回子串在字符串中首次出现的位置,用于检测是否存在子串。`SUBSTR`则用于提取字符串的子串。`LIKE`用于模糊匹配,常与通配符配合使用。注意`IN`并非用于判断子串包含。
|
28天前
|
SQL Java 程序员
Hive反射函数的使用-程序员是怎么学UDF函数的
Hive反射函数的使用-程序员是怎么学UDF函数的
7 0
|
1月前
|
SQL 数据处理 HIVE
【Hive】写出Hive中split、coalesce及collect_list函数的用法?
【4月更文挑战第17天】【Hive】写出Hive中split、coalesce及collect_list函数的用法?
|
1月前
|
SQL Java 数据处理
【Hive】Hive的函数:UDF、UDAF、UDTF的区别?
【4月更文挑战第17天】【Hive】Hive的函数:UDF、UDAF、UDTF的区别?
|
1月前
|
SQL HIVE 索引
Hive【Hive(五)函数-高级聚合函数、炸裂函数】
Hive【Hive(五)函数-高级聚合函数、炸裂函数】