HiveQL 行列转换样例

列转行

数据文件内容 player.txt

詹姆斯|小皇帝|2003|骑士,热火,湖人|3
保罗|三炮|2005|黄蜂,快船,火箭|0
韦德|闪电侠|2003|热火,骑士,公牛|3
安东尼|甜瓜|2003|掘金,尼克斯,雷霆,火箭|0

需求内容

将选秀年份相同且冠军数量相同的球员姓名用+拼接展示

2003,0|安东尼
2003,3|詹姆斯+韦德
2005,0|保罗

涉及函数解析

  • CONCAT_WS
CONCAT(string A/col, string B/col…):
返回输入字符串连接后的结果,支持任意个输入字符串;  

CONCAT_WS 是一个特殊形式的 CONCAT()()。  
CONCAT_WS(separator, str1, str2,...)
第一个参数剩余参数间的分隔符。
分隔符可以是与剩余参数一样的字符串。
如果分隔符是 NULL,返回值也将为 NULL。
这个函数会跳过分隔符参数后的任何 NULL 和空字符串。
分隔符将被加到被连接的字符串之间;
  • COLLECT_SET
COLLECT_SET(col):
函数只接受基本数据类型,
它的主要作用是将某字段的值进行去重汇总,
产生array类型字段。

开始实现

创建表接收数据

CREATE TABLE NBA_PLAYER(
  player_name     string  comment "球员姓名", 
  nickname        string  comment "外号",
  begin_year      varchar(4)  comment "选秀年份",
  join_team       string  comment "效力过的球队",
  champion_count  int  comment "总冠军次数"
 )ROW FORMAT DELIMITED FIELDS TERMINATED BY "|";

把数据从本地加载进数据表中

LOAD DATA LOCAL INPATH '/home/hadoop/player.txt' 
OVERWRITE INTO TABLE NBA_PLAYER ;

拼接字段函数 CONCAT_WS

SELECT CONCAT_WS(",",begin_year,CAST(champion_count AS STRING)) group_info,player_name 
 FROM NBA_PLAYER;

-- 查询结果
2003,3  詹姆斯
2005,0  保罗
2003,3  韦德
2003,0  安东尼

完成列转行 COLLECT_SET

SELECT  A.group_info,
        CONCAT_WS("+",COLLECT_SET(A.player_name))
FROM (
       SELECT CONCAT_WS(",",begin_year,CAST(champion_count AS STRING)) group_info,
              player_name
        FROM NBA_PLAYER
      ) A
GROUP BY A.group_info;

-- 查询结果
2003,0  安东尼
2003,3  詹姆斯+韦德
2005,0  保罗

简单例子:把选秀年份相同球员找到并放到一起+分割展示

SELECT  begin_year,
        CONCAT_WS("+",COLLECT_SET(player_name))
FROM  NBA_PLAYER
GROUP BY begin_year;

--  查询结果
2003    詹姆斯+韦德+安东尼
2005    保罗 

行转列

需求内容

统计每个球队效力过球员人数

涉及函数解析

  • explode(array
explode函数以array类型数据输入,然后对数组中的数据进行迭代,返回多行结果,一行一个数组元素值
ARRAY函数是将一列输入转换成一个数组输出。

Hive的表生成函数只是生成了一种数据的展示方式,
而无法在表中产生一个其他的列。   
因此这块需要使用LATERAL  VIEW 功能来进行处理。
LATERAL VIEW将explode生成的结果当做一个视图来处理。        
  • LATERAL VIEW
# 使用方法
LATERAL VIEW udtf(expression) tableAlias AS columnAlias

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

LATERAL VIEW 会将UDTF生成的结果放到一个虚拟表中  
然后这个虚拟表会和输入行进行join  
来达到连接UDTF外的select字段的目的
  • split
# 使用方法: 
split(string str, string pat)
返回值: array

按照pat字符串分割str,会返回分割后的字符串数,  
正则表达式中的特殊符号作为分隔符时,需做转义 (前缀加上\)

实现 字符串转数组 -> 行转列 -> 分组统计

SELECT player_name,
       join_team_name
FROM (
     SELECT player_name,
            split(join_team,",")  AS array_join_team
     FROM NBA_PLAYER
     ) A  
LATERAL VIEW EXPLODE(array_join_team) tmpTable AS join_team_name;

--- 查询结果
詹姆斯 骑士
詹姆斯 热火
詹姆斯 湖人
保罗  黄蜂
保罗  快船
保罗  火箭
韦德  热火
韦德  骑士
韦德  公牛
安东尼 掘金
安东尼 尼克斯
安东尼 雷霆
安东尼 火箭

SELECT  join_team_name , 
        COUNT(*) 
FROM (
      SELECT player_name,
             join_team_name
      FROM (
           SELECT player_name,
                  split(join_team,",")  AS array_join_team
           FROM NBA_PLAYER
           ) A  
      LATERAL VIEW EXPLODE(array_join_team) tmpTable AS join_team_name
      ) B
GROUP BY join_team_name;

--- 查询结果
公牛  1
尼克斯 1
快船  1
掘金  1
湖人  1
火箭  2
热火  2
雷霆  1
骑士  2
黄蜂  1

你可能感兴趣的:(HiveQL 行列转换样例)