行转列:

行转列其实就是把多行的数据连接在一起,放到一列里面,所用的函数是连接函数

concat(xx,xx) 连接到一起
concat_ws(separator, str1, str2,…) 这个多了一个separator分隔符,就是两个字符串之间用什么隔开

collect_set() 这个表示的是把某个字段进行去重汇总,产生一个array类型的字段

比如下面表的数据

name   constellation   blood_type
孙悟空	白羊座		A
老王	射手座		A
宋宋	白羊座		B       
猪八戒	白羊座		A
凤姐	射手座		A

把星座和血型一类的归为一起:

射手座,A            老王|凤姐
白羊座,A            孙悟空|猪八戒
白羊座,B            宋宋

首先我们可以先把 血型和星座连接到一起:

select concat(constellation,',',blood_type) as temp,name from person_info;
或者
select concat_ws(',',constellation,blood_type) as temp,name from person_info;

结果:

+---------------+-------+--+
|     temp      | name  |
+---------------+-------+--+
| 白羊座,A         | 孙悟空   |
| 射手座,A         | 老王    |
| 白羊座,B         | 宋宋    |
| 白羊座,A         | 猪八戒   |
| 射手座,A         | 凤姐    |

接下来就是要对temp 进行分组合并,用到collect_set() temp转为一个数组:

select t.temp,collect_set(name) from (  
    select concat_ws(',',constellation,blood_type) as temp,name
    from person_info
)t group by t.temp;

结果如下:

+---------------+----------------+--+
|    t.temp     |      _c1       |
+---------------+----------------+--+
| 射手座,A         | ["老王","凤姐"]    |
| 白羊座,A         | ["孙悟空","猪八戒"]  |
| 白羊座,B         | ["宋宋"]         |
+---------------+----------------+--+

之后再把数组拆分就好了:

select t.temp,concat_ws('|',collect_set(name)) from (  
    select concat_ws(',',constellation,blood_type) as temp,name
    from person_info
)t group by t.temp;

结果:

+---------------+----------+--+
|    t.temp     |   _c1    |
+---------------+----------+--+
| 射手座,A         | 老王|凤姐    |
| 白羊座,A         | 孙悟空|猪八戒  |
| 白羊座,B         | 宋宋       |
+---------------+----------+--+

列转行:

列传行其实就是将一列中的数据拆分为多行
需要用的函数是explode() 将一列中的array,map等拆分为多行,这个通常与lateral view一起连用,lateral view可以将explode 打散的数据和其他列连起来形成虚拟表,lateral view主要解决在select使用UTF做查询过程中,查询只能包含单个UDTF,不能包含其他字段、以及多个UDTF的问题, 有点难理解,看下面的例子:
数据:

《疑犯追踪》	悬疑,动作,科幻,剧情
《Lie to me》	悬疑,警匪,动作,心理,剧情
《战狼2》	战争,动作,灾难

需求是将结果展开如下:

《疑犯追踪》	悬疑
《疑犯追踪》	动作
《疑犯追踪》	科幻
《疑犯追踪》	剧情
《Lie to me》	悬疑
《Lie to me》	警匪
《Lie to me》	动作
《Lie to me》	心理
《Lie to me》	剧情
《战狼2》	战争
《战狼2》	动作
《战狼2》	灾难

首先创建表,并将数据导入到表中,创建表语句如下:

create table movie_info(movie string, category array<string>) 
row format delimited fields terminated by "\t" 
collection items terminated by ",";

之后我们就可以将数据打散了:

select explode(category) from movie_info;

结果如下:

+------+--+
| col  |
+------+--+
| 悬疑   |
| 动作   |
| 科幻   |
| 剧情   |
| 悬疑   |
| 警匪   |
| 动作   |
| 心理   |
| 剧情   |
| 战争   |
| 动作   |
| 灾难   |
+------+--+

到这看起来很简单,直接加上电影名,不就可以了么:

select movie,explode(category) from movie_info;

但是很遗憾的是报错了:

UDTF's are not supported outside the SELECT clause, nor nested in expressions

所以这个时候就用到lateral view,他可以将其转为一张虚拟的表并和前面的数据结合

select movie,category_name from movie_info lateral view explode(category) table_tmp
 as category_name;

结果:

+--------------+----------------+--+
|    movie     | category_name  |
+--------------+----------------+--+
| 《疑犯追踪》       | 悬疑             |
| 《疑犯追踪》       | 动作             |
| 《疑犯追踪》       | 科幻             |
| 《疑犯追踪》       | 剧情             |
| 《Lie to me》  | 悬疑             |
| 《Lie to me》  | 警匪             |
| 《Lie to me》  | 动作             |
| 《Lie to me》  | 心理             |
| 《Lie to me》  | 剧情             |
| 《战狼2》        | 战争             |
| 《战狼2》        | 动作             |
| 《战狼2》        | 灾难             |
+--------------+----------------+--+

如果导入的数据格式不是array,只是一个字符串的话,也可以用split 进行切分,之后在打散也是可以的:

select movie, category_name from movie_info2 lateral view explode(split(category,',')) tab
 as category_name;