例如,定义表:
create table example (
device_id string,
login_ip array,
user_info map>
address structstring,city:string,state:string>
)
row format delimited
fields terminated by '\001' collection items terminated by '\002' map keys terminated by '\003' lines terminated by '\n' stored as RCFile;
1
2
3
4
5
6
7
8
9
10
11
12
在hive环境下运行,即可创建该管理表(区分外部表),如果有必要,可以直接使用load data加载数据。
collect_set函数(行转列)
collect_set(col)函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段。例如,如下数据记录,要统计每种no下的score,这里就可以配合group by 产生奇效。
no score 1 2 1 3 1 3 2 2 2 4 2 4 ......1
2
3
4
5
6
7
8
直接对no分组后对score进行collect_set操作,如下:
select no,collect_set(score) from tablss group by no;
这样,就实现了将列转行的功效,但是注意只限同列基本数据类型,函数只能接受一列参数。
有以下表
id
name
1001
A
1001
B
1001
C
实现以下功能
id
name
1001
A,B,C
即按照id 进行group by,将每个id的name组成一个list放到name字段中。
select id,collect_list(name) from table group by id1
若name中有重复的值,可以用collect_set函数进行去重
collect_list函数返回的类型是array< ? >类型,?表示该列的类型
怎么转为string类型?
我们可以使用concat_ws函数,但是该函数仅支持string和array< string > 所以对于该列不是string的列,先转为string
select id,concat_ws(',',collect_list(cast (name as string))) from table group by id1
最终实现了我们需要的输出结果
concat_ws函数的意思是用逗号将所有的string组合到一起,用逗号分割显示
select concat_ws(',',"A","B");1
上面代码的结果就是
A,B
explode函数
explode(array)函数接受array类型的参数,其作用恰好与collect_set相反,实现将array类型数据行转列,例如,上述记录列转行后的形式如下:
no score_set 1 [2,3] 2 [2,4]1
2
3
假设这样的数据类型以分区表存储,你要统计一段时间类no=1下的去重score,那么该怎么办了?这里可配合使用lateral view首先实现列转行的功能,如下所示:
select no,score from tablaa lateral view explode(score_set) xxx as score;
注:xxx代表虚表名称,不能缺少。
进一步深化上述代码解决统计一段时间的去重值,可写为:
select no,collect_set(score) from tablaa lateral view explode(score_set) xxx as score group by no;
这样,将两个函数结合实现了行转列或列转行的妙用。
列转行可用到explode
hive> select explode(split(concat_ws(',','1','2','3','4'),',')) from default.dual; 1
2
3
41
2
3
4
5
表示1,2,3,4拼接起来,然后再用逗号分隔成列,应用到表中如下面所示
hive> select * from tt s lateral view explode(split("a b c d"," ")) t3 as sp; ------需要起别名,tt表中只有一个字段有数据。 A a
A b
A c
A d