哈喽,大家好呀,我是胖里,新的一周我们又见面啦!
这两天黄老板退任的消息满天飞,有的文章说他退任不退休,可我好想退休啊,真想一觉醒来就发现自己退休了!不知道你们有没有想退休的想法,有的话可以悄悄告诉我!
今天想跟大家聊一聊Hive中常见的两种复合数据类型:Map、Array。
全篇共计2310字,预计阅读时间6分钟。
1
背景
昨天下午,同事说要跟我请教一个问题,有大概如下一张表,问:如何能判断字段B中包含56?(其中字段A的数据类型为string,字段B的数据类型为array)

我:
你like一下?不对哦,万一有156,256这种呢?
不然把array split一下?不行哦,array长度不固定,且有的挺长。
有没有函数啊?应该会有函数吧?
一问ETL大佬,array_contains()一下就行了。
你看,总有那些方便、好用但你在字面上没见过的函数,就如同之前说的窗口函数,有很多,可能你无法一一认识它们,但你可以在实操、向别人请教中学到。
学到了array_contains()这个函数,我微微有点兴奋,想着借此把接触过的一些跟Hive复合数据类型相关的函数或操作记录一下,如果你早就知道了,那你真的太棒了,如果你还不知道,恭喜你!学了新知识!
2
Array 相关
Array就是数组,跟你在其他编程语言中认识的一样,里面存储了0个或多个元素,比如['幼儿园','小学','初中','高中',大学'],这就是一个array。
1. Array的创建
我去翻了翻别人的资料,一般都是长这个样子。

我在实际工作中一般直接接触的公司平台,只需要HQL写好,粘贴进对应位置进行建表操作就OK了,一般我的array类型的数据来源有两个,第一个是从上游表中select某些字段,其类型是array,所以我复制过来的时候也需要搞一个array类型的字段。第二个是在处理一些量很大的数据时,比如用户日志,会根据用户id将其某些信息进行整合,存储到一个array中。
所以我一般建表用到array的时候就是这样子。

2. Array的一些操作
对于array的一些操作,主要说几个日常中常见的,涉及array的生成、拆分、查找、及其他的几个操作函数。
A. Array的生成
我在刚刚array的创建中提及了一个函数collect_set(),使用这个函数我们就可以根据不同的key进行分组,将其他信息合并为一个array。
除此之外,也可以采用collect_list()、concat_ws()、group_concat()。
它们之间的区别是:
collect_set()对合并后的array中的数据去重;
collect_list()对合并后的的array中的数据不去重;
concat_ws()可自定义分隔符进行array的生成;
group_concat()可自定义分隔符进行array的生成;
现实中按某列分组聚合时,记得别忘记group by 列。
B. Array的拆分
关于array的拆分,可以使用split()和lateral view explode,即可实现A中合并数组的拆分,恢复原貌。
C. Array的查找
与其叫array的查找,不如叫在array中查找,回到背景里遇到的那个问题,想着数组中快速找到某一字符,直接上array_contains()函数就行,无需拆分,快速实现array中数据定位。
除此之外,也可以试试find_in_set()。
D. Array的其他操作
还想提两个可能会用到的函数:sort_array()和size(),实现对array中数据的排序和计数操作,其中需要注意的是sort_array()只能进行升序操作。
3
Map 相关
Map又叫字典,也跟其他编程语言中认识的一样,map里以key-value的形式存储了对应的数据。
1. Map的创建
同样还是翻了别人的资料,一般长这样。

与array相似,实际工作中,我的map类型的数据来源一般只有一个,那就是select上游表的数据。埋点的时候一些次要信息可能会一股脑地塞进某个map中,经过数仓处理,到业务层面来,也是以map类型存储。

2. Map的一些操作
对于Map的一些操作,也主要说几个日常中常见的,如map的查询、计数。
size()函数既可以对array的长度进行统计,也可以对map的长度进行统计;
map_keys()函数可得到map中所有的key值,格式为array;
map_values()函数可得到map中所有的value值,格式为array;
既然如此,想从map中查询到某个值,是不是也可以用array_contains()?答案是YES!先用相应函数转为array,再查询定位具体值。
4
结尾
还想介绍一个在我日常工作中经常用到的函数get_json_object(),用于对json字符串进行解析。表中常有一些声称自己是string类型的字段,以为很友善,展开一看长得可吓人,比如:

要想从p中取email地址,就得:
select get_json_object(p, '$.email') from table;
要想取到bag的price呢?
select get_json_object(p, '$.store.bag.price') from table;
上述例子都是解析了p中的一个字段,若是想同时解析store、email和owner字段呢?当然可以用三个get_json_object()实现,也可以使用json_tuple结合lateral view进行多个字段的解析。
好了,今天的分享就到这里了,希望以后能有机会多给你们分享胖里的日常,也欢迎大家私信我分享自己的日常。
感兴趣的小伙伴可以后台回复关键字「开心交流群」入群交流。
我是胖里,感谢有你。




