HQL中实现行列转换
其实并不用纠结哪个是行转列、哪个是列转行,明白二者之间的需求即可
在Hive sql应用中会遇到“行转列”和“列转行”的场景,下面介绍其基本使用语法。
1.行转列:
关键字:collect_set() / collect_list()、concat_ws()
1)collect_set()/collect_list():
collect_set( )函数只接受基本数据类型,作用是对参数字段进行去重汇总,返回array类型字段;
collect_list()函数和collect_set( )作用一样,只是前者不去重,后者去重。
2)concat_ws():
concat_ws (separator,字符串A/字段名A,字符串B/字段名B…)是concat的特殊形式,第一个参数是分隔符,分隔符会放到要连接的字符串之间,分隔符可以是字符串,也可以是其他参数。如果分隔符为NULL,则结果为NULL,函数会忽略任何分隔符参数后的 NULL值。但是concat_ws( )不会忽略任何空字符串。(然而会忽略所有的 NULL),如果参数为string类型数组则合并数组内字符串。
例:concat_ws( ‘,’, [ ‘a ‘, ‘b’])–> ‘a,b’
行转列基本语法:
select 分类字段,concat_ws(’,’,collect_set(合并字段)) as 别名 from table_name group 分类字段;
/* 原始数据
name gender times
张三 男 唐
李四 男 唐
王五 男 明
赵六 男 明
*/
-- 先用collect_set将列拼接在一起,然后再通过concat_ws进行展开拼接
SELECT a.gender_times,
concat_ws(';',collect_set(a.name)) name
FROM
(SELECT name,
concat(gender, '_','times') gender_times
FROM hero_info) t
GROUP BY t.gender_times;
/*查询结果
gender_times name
男_唐 张三;李四
男_明 王五;赵六
2.列转行
关键字:explode()、split()和LATERAL VIEW
/*原始数据
province city
河南 郑州市,开封市,洛阳市
河北 石家庄市,保定市
湖南 长沙市,岳阳市,常德市
*/
-- addr为表名
SELECT province,
city_n
FROM addr LATERAL VIEW explode (split(city,',')) addr_tmp AS city_n;
/*
-- 查询结果
河南 郑州市
河南 开封市
河南 洛阳市
河北 石家庄市
河北 保定市
湖南 长沙市
湖南 岳阳市
湖南 常德市
*/
下面再用别的例子进行阐述一下
行转列
数据、建表如下:
张三 白羊座 A
李四 射手座 A
王五 白羊座 B
刘六 白羊座 A
诸葛七 射手座 A
小明 白羊座 B
create table person_info(
name string,
constellation string,
blood_type string)
row format delimited fields terminated by "\t";
需求如下:
把星座和血型一样的人归类到一起
射手座,A 大海|凤姐
白羊座,A 张三|刘六
白羊座,B 王五|小明
分析:
先用concat_ws函数将将星座和血型用“,”连接
在根据连接好的星座和血型group by
用collect_set函数对name聚合,
用concat_ws函数对聚合后的name用“|”分割
实现如下:
SELECT
t1.c_b,
CONCAT_WS("|",collect_set(t1.name))
FROM (
SELECT
NAME,
CONCAT_WS(',',constellation,blood_type) c_b
FROM person_info
)t1
GROUP BY t1.c_b
列转行
数据、建表如下:
《疑犯追踪》 悬疑,动作,科幻,剧情
《Lie to me》 悬疑,警匪,动作,心理,剧情
《战狼 2》 战争,动作,灾难
create table movie_info(
movie string,
category string)
row format delimited fields terminated by "\t";
需求如下:
将电影分类中的数组数据展开
《疑犯追踪》 悬疑
《疑犯追踪》 动作
《疑犯追踪》 科幻
《疑犯追踪》 剧情
《Lie to me》 悬疑
《Lie to me》 警匪
《Lie to me》 动作
《Lie to me》 心理
《Lie to me》 剧情
《战狼 2》 战争
《战狼 2》 动作
《战狼 2》 灾难
分析:
先用split函数将category根据“,”分割成数组
lateral view结合explode函数进行炸裂后的侧写
实现如下:
SELECT
movie,
category_name
FROM
movie_info
lateral VIEW
explode(split(category,",")) movie_info_tmp AS category_name;