这个函数大多数人都接触过,将一行数据转换成列数据,能够用于array和map类型的数据。程序员
用于array的语法以下:sql
select explode(arraycol) as newcol from tablename;
用于map的语法以下:express
select explode(mapcol) as (keyname,valuename) from tablename;
注意:这两个值须要在as以后用括号括起来而后以逗号分隔。函数
以上为explode()函数的用法,此函数存在局限性:测试
lateral view是Hive中提供给UDTF的结合,它能够解决UDTF不能添加额外的select列的问题。.net
lateral view其实就是用来和想相似explode这种UDTF函数联用的,lateral view会将UDTF生成的结果放到一个虚拟表中,而后这个虚拟表会和输入行进行join来达到链接UDTF外的select字段的目的。code
lateral view udtf(expression) tableAlias as columnAlias (,columnAlias)*
from basetable (lateral view)*
from basetable (lateral view outer)*
它比格式二只是多了一个outer,这个outer的做用是在UDTF转换列的时候将其中的空也给展现出来,UDTF默认是忽略输出空的,加上outer以后,会将空也输出,显示为NULL。这个功能是在Hive0.12是开始支持的。orm
下面来讲一个需求案例。blog
有一张hive表,分别是学生姓名name(string),学生成绩score(map<string,string>),成绩列中key是学科名称,value是对应学科分数,请用一个hql求一下每一个学生成绩最好的学科及分数、最差的学科及分数、平均分数。get
表数据以下:
zhangsan|Chinese:80,Math:60,English:90 lisi|Chinese:90,Math:80,English:70 wangwu|Chinese:88,Math:90,English:96 maliu|Chinese:99,Math:65,English:60
下面来作一下准备工做,建立表,并将数据导入表中,操做以下:
建立表:
create table student_score(name string,score map<String,string>) row format delimited fields terminated by '|' collection items terminated by ',' map keys terminated by ':';
导入数据:
load data local inpath '/home/test/score' overwrite into table student_score;
检查一下数据,以下图:
确认数据导入没有问题。
首先要处理这个表中的数据,本人第一想法是想找一下Hive有没有内置的操做map复杂类型的函数,惋惜看了一遍,没有找到,这个思路只能放弃。
第二想法,是将map中的数据转换成一个虚拟表,而后与name字段关联,这样造成一张可操做的虚拟表。在查阅了资料以后,看到explode()函数能够作这个事情,首先写了一条语句:
select explode(score) from student_score; select explode(score) as (key,value) from student_score;
结果:
此函数验证了它倒是能够作到分离map的功能,将行转为列,难么既然行转了列,那么只须要将name字段关联上,就能够进行统计操做了。
惋惜的是,explode函数怎么使用,都关联不了name字段。
既然Hive有这些东西,确定可以作到关联其余字段的,这是本人做为一个程序员的信念,若是没有的话,这个功能作出来就是鸡肋了,只有关联了其余能够肯定其为惟一消息的字段,这样的功能才又意义。
又在网上查询到,常常和explode函数和用的就是lateral view函数,那么这两个结合就能作到关联其余字段。写法以下:
select name,key,value from student_score lateral view explode(score) scntable as key,value;
结果以下:
看到上面的数据,就是咱们想要的结果,产生了这样一个虚拟表以后,全部的工做都变的简单了起来。
从上面两条语句能够看出,explode在select句中和在from子句中给虚拟字段命名的格式稍微有些差异,select句中须要加括号,from子句中不须要括号。
以上是这个需求的难点,其余的就不在作过多的说明。
下面将结果抛出来,这可能不是最优的,可是是一种方式:
select sname,gk,gv,bk,bv,av from ( select * from ( select C.name as sname,C.key as gk,C.value as gv from ( select name,max(value) as gv from ( select name,key,value from student_score lateral view explode(score) scnTable as key,value) as A group by name) as B left join (select name,key,value from student_score lateral view explode(score) scnTable as key,value) as C on B.name=C.name and B.gv=C.value) as GG left join (select C.name as bname,C.key as bk,C.value as bv from (select name,min(value) as bv from ( select name,key,value from student_score lateral view explode(score) scnTable as key,value) as A group by name) as B left join (select name,key,value from student_score lateral view explode(score) snTable as key,value) as C on B.name=C.name and B.bv=C.value) as BB on GG.sname=BB.bname) as SS left join (select name as aname,avg(value) as av from ( select name,key,value from student_score lateral view explode(score) scnTable as key,value) as A group by name) AA on SS.sname=AA.aname
结果以下:
列名依次为:姓名、最好成绩的科目、分数、最差成绩的科目、分数、平均分
这里须要说一些,Hive中的基本数据类型,string类型应该是使用的自动转换机制,转换为了int,这里将score map<string,string>声明为score map<string,int>也是能够的。
本人的hive环境为1.1.0CDH5版,此时将上面的数据作一下修改,来测试一下outer的做用,数据以下:
zhangsan|Chinese:80,Math:60,English:90 lisi|Chinese:90,Math:80,English:70 wangwu|Chinese:88,Math:90,English:96 maliu|Chinese:99,Math:65,English:
将maliu的英语成绩给去掉,而后导入到表中。
在执行如下语句:
select explode(score) from student_score;
结果以下:
能够看到最后一个English的成绩没有显示任何东西,也就是被UDTF给忽略了。
下面使用lateral view看一下:
select name,key,value from student_score lateral view explode(score) scntable as key,value;
结果以下:
最后加上outer在试一下:
select name,key,value from student_score lateral view outer explode(score) scntable as key,value;
结果以下:
结果和没加outer是同样的,这就又是一个新的问题了,outer是否只对arrary类型的有效,对map类型无效呢?
本人又将arrary类型进行了测试,和map一样,都是什么都不显示,只是将没有的一列作了联表匹配。
这个问题有待研究。
上一篇:Hive语法:union
下一篇: