Hive面试题2:hive中的行转列、列转行

面试时经常会被问到,hive中行转列、列转行怎么做?

除了可以使用case when语句来进行行转列,hive中还有内置的函数,可以很方便的实现行转列
多行转单列使用: concat_ws + collect_set
单列转多行: lateral view + explode

函数说明
explode函数可以将array或map展开---- explode(array)将array里的每一个元素作为一行; explode(map)将map中的每一对元素作为一行,key为一列,value为一列

lateral view为侧视图,用来配合UDTF函数使用。 不加lateral view的UDTF只能提取单个字段拆分,并不能塞回原来数据表中.加上lateral view就可以将拆分的单个字段数据与原始表数据关联上。 写法格式:
表名 lateral view UDTF(xxx) 视图别名 as 新列别名

具体操作案例,如下:

hive中的行转列

数据表

col1	col2	col3
a	b	1
a	b	2
a	b	3
c	d	4
c	d	5
c	d	6

将其转化为

col1	col2	col3
a	b	1,2,3
c	d	4,5,6

多行转单列: concat_ws + collect_set

CONCAT_WS()使用语法为:CONCAT_WS(separator,str1,str2,…)
CONCAT_WS() 代表 CONCAT With Separator ,是CONCAT()的特殊形式。第一个参数是其它参数的分隔符。分隔符的位置放在要连接的两个字符串之间。分隔符可以是一个字符串,也可以是其它参数。如果分隔符为 NULL,则结果为 NULL。函数会忽略任何分隔符参数后的 NULL 值。但是CONCAT_WS()不会忽略任何空字符串。 (然而会忽略所有的 NULL)。

hive> desc function extended concat_ws;
OK
concat_ws(separator, [string | array(string)]+) - returns the concatenation of the strings separated by the separator.
Example:
  > SELECT concat_ws('.', 'www', array('facebook', 'com')) FROM src LIMIT 1;
  'www.facebook.com'

示例演示:

创建数据

vim /root/temp/row2col_1.csv

数据

a	b	1
a	b	2
a	b	3
c	d	4
c	d	5
c	d	6

创建表

create table row2col_2(col1 string,col2 string,col3 int) row format delimited fields terminated by '\t';

加载数据

load data local inpath '/root/temp/row2col_1.csv' into table row2col_2;

加载出错可以修改数据后覆盖数据

load data local inpath '/root/temp/row2col_1.csv' overwrite into table row2col_2;

collect_set转换

select col1,col2,concat_ws(',',collect_set(cast(col3 as string))) as col3 from row2col_2 group by col1,col2;

或者使用collect_list

select col1,col2,concat_ws(',',collect_list(cast(col3 as string))) as col3 from row2col_2 group by col1,col2;

显示

a       b       1,2,3
c       d       4,5,6

转换

select col1,col2,concat_ws(',',collect_set(col3)) as col3 from row2col_2 group by col1,col2;

会报出错误

hive> select col1,col2,concat_ws(',',collect_set(col3)) as col3 from row2col_2 group by col1,col2;
FAILED: SemanticException [Error 10016]: Line 1:31 Argument type mismatch 'col3': Argument 2 of function CONCAT_WS must be "string or array<string>", but "array<int>" was found.

需要转换成string。

结果显示如下:

a       b       1,2,3
c       d       4,5,6

还可以使用group_concat()分组拼接函数,不过hive的环境不支持,mysql中有这个
group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])

扩展

Hive中collect相关的函数有collect_list和collect_set

它们都是将分组中的某列转为一个数组返回,不同的是collect_list不去重而collect_set去重。

collect_set(col)函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段。

hive中的列转行

单列转多行: lateral view + explode

将数据表col2row2

col1	col2	col3
a       b       1,2,3
c       d       4,5,6

将其转换为

col1	col2	col3
a       b       1
a       b       2
a       b       3
c       d       4
c       d       5
c       d       6

这里需要使用UDTF(表生成函数)explode(),该函数接受array类型的参数,其作用恰好与collect_set相反,实现将array类型数据行转列。explode配合lateral view实现将某列数据拆分成多行

explode()接受一个数组(或一个map)作为输入,并将数组元素(map)作为单独的行输出。 UDTF可以在SELECT表达式列表中使用,也可以作为LATERAL VIEW的一部分使用。

hive> desc function extended explode;
OK
explode(a) - separates the elements of array a into multiple rows, or the elements of a map into multiple rows and columns 
Time taken: 0.005 seconds, Fetched: 1 row(s)

lateral view

配合explode(或者其他的UDTF),一个语句生成把单行数据拆解成多行后的数据结果集。

lateral view为侧视图,用来配合UDTF函数使用。 不加lateral view的UDTF只能提取单个字段拆分,并不能塞回原来数据表中.加上lateral view就可以将拆分的单个字段数据与原始表数据关联上。 写法格式:

表名 lateral view UDTF(xxx) 视图别名 as 新列别名

select subview.* from test_message lateral view explode(location) subview as lc;

subview为视图别名,lc为指定新列别名

依据上次查询的结果来创建表

 create table row2col_3 as select col1,col2,concat_ws(',',collect_set(cast(col3 as string))) as col3 from row2col_2 group by col1,col2;

查询一下

a       b       1,2,3
c       d       4,5,6

转换的语句

select col1,col2,lv.col3 as col3
from row2col_3
lateral view explode(split(col3,',')) lv as col3;

或者直接使用

这里是必须使用别名来进行操作,如果和原来的别名一样 还必须使用.号来进行区分

select col1,col2,col4
from row2col_3
lateral view explode(split(col3,',')) lv as col4;

结果显示

a       b       1
a       b       2
a       b       3
c       d       4
c       d       5
c       d       6
发布了35 篇原创文章 · 获赞 12 · 访问量 6639

猜你喜欢

转载自blog.csdn.net/u012955829/article/details/102810694
今日推荐