赞
踩
姓名(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 |
将上⾯⾏转多列的结果再转回成原始表结构的过程,就是多列转⾏
思路
列转⾏,会涉及到⾏数的增加,所以会⽤到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 |
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 | 青岛,六安 |
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 | 六安 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。