Hive之--行转列collect和列转行explode

一、行专列

1.相关函数说明

  • concat(string A/col, string B/col…):返回输入字符串连接后的结果,支持任意个输入字符串;
  • concat_ws(separator, str1, str2,...):它是一个特殊形式的 concat()。第一个参数剩余参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;
  • collect_set(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段。
  • collect_list(col):与collect_set作用相似,区别不去重字段,产生array类型字段。

2. 数据准备

name

constellation

blood_type

孙悟空

白羊座

A

大海

射手座

A

宋宋

白羊座

B

猪八戒

白羊座

A

凤姐

射手座

A

3. 创建本地constellation.txt,导入数据

[hadoop@hadoop112 datas]$ vi constellation.txt 
孙悟空	白羊座	A
大海	射手座	A
宋宋	白羊座	B
猪八戒	白羊座	A
凤姐	射手座	A
苍老师	白羊座	B

4. 创建hive表并导入数据

create table person_info(
name string, 
constellation string, 
blood_type string) 
row format delimited fields terminated by "\t";
load data local inpath "/opt/module/datas/constellation.txt" into table person_info;

5. 表中数据

0: jdbc:hive2://hadoop112:10000> select * from person_info;
+-------------------+----------------------------+-------------------------+--+
| person_info.name  | person_info.constellation  | person_info.blood_type  |
+-------------------+----------------------------+-------------------------+--+
| 孙悟空               | 白羊座                        | A                       |
| 大海                | 射手座                        | A                       |
| 宋宋                | 白羊座                        | B                       |
| 猪八戒               | 白羊座                        | A                       |
| 凤姐                | 射手座                        | A                       |
| 苍老师               | 白羊座                        | B                       |
+-------------------+----------------------------+-------------------------+--+
6 rows selected (0.058 seconds)
0: jdbc:hive2://hadoop112:10000> 

6. concat的用法

执行如下HQL:

select 
   concat(constellation,",",blood_type) xx,
   count(*) geshu
from 
   person_info
group by 
  constellation,
  blood_type;

结果如下:

+--------+--------+--+
|   xx   | geshu  |
+--------+--------+--+
| 射手座,A  | 2      |
| 白羊座,A  | 2      |
| 白羊座,B  | 2      |
+--------+--------+--+

7. concat_list函数的用法

0: jdbc:hive2://hadoop112:10000> desc function  collect_list;
+--------------------------------------------------------------+--+
|                           tab_name                           |
+--------------------------------------------------------------+--+
| collect_list(x) - Returns a list of objects with duplicates  |
+--------------------------------------------------------------+--+
1 row selected (0.023 seconds)
0: jdbc:hive2://hadoop112:10000> 

执行如下HQL:

select 
    concat(constellation,",",blood_type) xx,
    collect_list(name) names
from 
    person_info
group by
    constellation,
    blood_type;

结果显示如下:

+--------+----------------+--+
|   xx   |     names      |
+--------+----------------+--+
| 射手座,A  | ["大海","凤姐"]    |
| 白羊座,A  | ["孙悟空","猪八戒"]  |
| 白羊座,B  | ["宋宋","苍老师"]   |
+--------+----------------+--+

8. concat_ws的用法,把array数组转换为字符串

0: jdbc:hive2://hadoop112:10000> desc function  concat_ws;
+-------------------------------------------------------------------------------------------------------------------------+--+
|                                                        tab_name                                                         |
+-------------------------------------------------------------------------------------------------------------------------+--+
| concat_ws(separator, [string | array(string)]+) - returns the concatenation of the strings separated by the separator.  |
+-------------------------------------------------------------------------------------------------------------------------+--+
1 row selected (0.023 seconds)

执行如下HQL:

select 
    concat_ws(",",constellation,blood_type) xx,
    concat_ws(",",collect_list(name)) names
from 
    person_info
group by
    constellation,
    blood_type;

结果显示如下:

+--------+----------+--+
|   xx   |  names   |
+--------+----------+--+
| 射手座,A  | 大海,凤姐    |
| 白羊座,A  | 孙悟空,猪八戒  |
| 白羊座,B  | 宋宋,苍老师   |
+--------+----------+--+

二、列转行

1. 相关函数说明

  • explode(col):将hive一列中复杂的array或者map结构拆分成多行。
  • lateral view 

用法:lateral view  udtf(expression) tableAlias AS columnAlias

解释:用于和split, explodeUDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。

2. 数据准备

movie

category

《疑犯追踪》

悬疑,动作,科幻,剧情

《Lie to me》

悬疑,警匪,动作,心理,剧情

《战狼2》

战争,动作,灾难

3. 创建本地movie.txt,导入数据

[hadoop@hadoop112 datas]$ vi movie.txt 
《疑犯追踪》	悬疑,动作,科幻,剧情
《Lie to me》	悬疑,警匪,动作,心理,剧情
《战狼2》	战争,动作,灾难
[hadoop@hadoop112 datas]$ 

4. 创建hive表并导入数据

create table movie_info(
    movie string, 
    category array) 
row format delimited fields terminated by "\t"
collection items terminated by ",";
load data local inpath "/opt/module/datas/movie.txt" into table movie_info;

5. 查看表中数据

0: jdbc:hive2://hadoop112:10000> select * from movie_info;
+-------------------+-----------------------------+--+
| movie_info.movie  |     movie_info.category     |
+-------------------+-----------------------------+--+
| 《疑犯追踪》            | ["悬疑","动作","科幻","剧情"]       |
| 《Lie to me》       | ["悬疑","警匪","动作","心理","剧情"]  |
| 《战狼2》             | ["战争","动作","灾难"]            |
+-------------------+-----------------------------+--+
3 rows selected (0.054 seconds)
0: jdbc:hive2://hadoop112:10000> 

6. explode函数的用法

0: jdbc:hive2://hadoop112:10000> select explode(category) from movie_info;
+------+--+
| col  |
+------+--+
| 悬疑   |
| 动作   |
| 科幻   |
| 剧情   |
| 悬疑   |
| 警匪   |
| 动作   |
| 心理   |
| 剧情   |
| 战争   |
| 动作   |
| 灾难   |
+------+--+
12 rows selected (0.051 seconds)
0: jdbc:hive2://hadoop112:10000> desc function explode;

7. lateral view 函数的用法

执行如下HQL:

select movie,explode(category) from movie_info;

发现会报如下错误:

Error: Error while compiling statement: FAILED: SemanticException [Error 10081]: UDTF's are not supported outside the SELECT clause, nor nested in expressions (state=42000,code=10081)

则此时需用lateral view 函数实现以上功能,HQL如下:

select 
   movie_info.movie,
   tbl.c_name
from 
   movie_info
lateral view 
   explode(category) tbl as c_name;

查询结果如下:

+-------------------+-------------+--+
| movie_info.movie  | tbl.c_name  |
+-------------------+-------------+--+
| 《疑犯追踪》            | 悬疑          |
| 《疑犯追踪》            | 动作          |
| 《疑犯追踪》            | 科幻          |
| 《疑犯追踪》            | 剧情          |
| 《Lie to me》       | 悬疑          |
| 《Lie to me》       | 警匪          |
| 《Lie to me》       | 动作          |
| 《Lie to me》       | 心理          |
| 《Lie to me》       | 剧情          |
| 《战狼2》             | 战争          |
| 《战狼2》             | 动作          |
| 《战狼2》             | 灾难          |
+-------------------+-------------+--+
12 rows selected (0.058 seconds)
0: jdbc:hive2://hadoop112:10000> 

三、行转列和列转行综合应用案例

1. 实现category所包含的movie

实现HQL如下:

select
    categories,
    collect_set(movie) movies
from
    (select
    movie_info.movie,
    tbl.categories
from
    movie_info
lateral view 
explode(category) tbl as categories) t1
group by
    categories;

查询结果如下:

+-------------+-----------------------------------+--+
| categories  |              movies               |
+-------------+-----------------------------------+--+
| 剧情          | ["《疑犯追踪》","《Lie to me》"]          |
| 动作          | ["《疑犯追踪》","《Lie to me》","《战狼2》"]  |
| 心理          | ["《Lie to me》"]                   |
| 悬疑          | ["《疑犯追踪》","《Lie to me》"]          |
| 战争          | ["《战狼2》"]                         |
| 灾难          | ["《战狼2》"]                         |
| 科幻          | ["《疑犯追踪》"]                        |
| 警匪          | ["《Lie to me》"]                   |
+-------------+-----------------------------------+--+
8 rows selected (16.83 seconds)

2. 使用concat_ws上述结果中的movies列转换为string

实现HQL如下:

select
    categories,
    concat_ws("|",collect_set(movie)) movies
from
    (select
    movie_info.movie,
    tbl.categories
from
    movie_info
lateral view 
explode(category) tbl as categories) t1
group by
    categories;

查询结果如下:

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

四、总结

在上面的描述里我们可以看到:

  1. 列转行(UDTF):将一行变多行
  2. 行转列(UDAF):多行变一行
  3. 而且用到了几个函数
  4. concat(字段1,“分隔符”,字段2):连接两个字段
  5. concat_ws(“分隔符”,字段集合)分割集合内字段
  6. collect_list(字段):把字段放入集合等待处理,字段可以重复
  7. collect_set(字段):把字段放入集合等待处理,并具有去重功能

你可能感兴趣的:(Hive)