Hive行列转换

1.多行转多列

Hive行列转换_第1张图片

姓名(name) 学科(subject) 成绩(score)
A 语文 70
A 数学 80
A 英语 90
B 语文 75
B 数学 85
B 英语 95

行列转换思路分析及实现

多行转多列
如果需要将上⾯的样例表转换为

姓名 | 语⽂成绩 | 数学成绩 | 英语成绩

这样的格式,就是 多行转多列

思路:
涉及到行转成列,肯定是会按照某⼀列或者某⼏列的值进⾏分组来压缩⾏数,所以会⽤到group by。
分组之后需要⽤到聚合函数,由于多列中的每列只关⼼⾃⼰对应的数据,所以要使⽤case语句进⾏选择,⾄于聚合函数,只要数据能保证唯一性,max、min、avg(数值类型)等都可以

样例SQL

select
  name
  ,max(case subject when '数学' then score else 0 end) math
  ,max(case subject when '英语' then score else 0 end) english
  ,max(case subject when '语文' then score else 0 end) chinese
from ts
group by name;

输出过程

name chinese math english
A max(70,0,0) max(80,0,0) max(90,0,0)
B max(75,0,0) max(85,0,0) max(95,0,0)

输出结果

name chinese math english
A 70 80 90
B 75 85 95

2.多列转多行

Hive行列转换_第2张图片

将上⾯⾏转多列的结果再转回成原始表结构的过程,就是多列转⾏

思路
列转⾏,会涉及到⾏数的增加,所以会⽤到UDTF(一进多出),⽽UDTF只是针对某⼀列的,要把这列扩展后⽣成的多⾏数据和源表中的各列拼接在⼀起,需要⽤到lateral view语法;
需要将多列⾥各列的列名(业务含义),在新数据中当做⼀个标识列,⽽与lateral view联合使⽤的explode函数是⽀持Map类型的,所以要先将原表⾥的多列变换成Map类型的⼀列,然后再⽤lateral view拆开。

样例SQL

select name,subject,score from 
(
select name,map('语文',chinese,'数学',math,'英语',english) scores from 
(select
  name
  ,max(case subject when '语文' then score else 0 end) chinese
  ,max(case subject when '数学' then score else 0 end) math
  ,max(case subject when '英语' then score else 0 end) english
from ts
group by name)ts1
)ts2
lateral view explode(scores) ts3 as subject,score

ts1

name chinese math english
A 70 80 90
B 75 85 95

ts2

name scores
A {“语文”:“70”,“数学”:“80”,“英语”:“90”}
B {“语文”:“75”,“数学”:“85”,“英语”:“95”}

select explode(scores) from ts2;

key value
语文 70
数学 80
英语 90
语文 75
数学 85
英语 95

输出结果

name subject score
A 语文 70
A 数学 80
A 英语 90
B 语文 75
B 数学 85
B 英语 95

3.一列转一行

Hive行列转换_第3张图片

id num name
1 zs 合肥
1 ls 南京
1 ww 杭州
1 zl 重庆
1 sq 郑州
2 wb 六安
2 lq 青岛
3 dd 三亚
3 si 常州
3 sh 武汉

SQL

select id,collect_list(name) names from ts group by id;

输出结果

id names
3 [“三亚”,“常州”,“武汉”]
1 [“杭州”,“合肥”,“南京”,“郑州”,“重庆”]
2 [“青岛”,“六安”]

SQL 外面套一层concat_ws(),输出以’,'分割的字符串

select id,concat_ws(',',collect_list(name)) names from ts group by id;

输出结果

id names
3 三亚,常州,武汉
1 杭州,合肥,南京,郑州,重庆
2 青岛,六安

4.一行转一列

Hive行列转换_第4张图片

id names
3 三亚,常州,武汉
1 杭州,合肥,南京,郑州,重庆
2 青岛,六安

SQL

select id,name from ts1
lateral view explode(split(names,',')) lateral_name as name

输出结果

id name
3 三亚
3 常州
3 武汉
1 杭州
1 合肥
1 南京
1 郑州
1 重庆
2 青岛
2 六安

你可能感兴趣的:(hive,hadoop,数据仓库)