hive行列互换

hive行列互换

今天你用钱袋里的铜板充满你的内心,明天你的内心就可以把你的钱袋注满黄金。

目录

1.创建表

2.上传数据

3.实现需求

4.行列互换

1)行转列:    

2)列传行:

①如何转换:(案例)

②EXPLODE() 函数:将集合中的一行数据转换为多行

③示例2:增加一列数据

解析:  


1.创建表


CREATE EXTERNAL TABLE IF NOT EXISTS learn3.student20(
id STRING COMMENT "学生ID",
name STRING COMMENT "学生姓名",
age int COMMENT "年龄",
gender STRING COMMENT "性别",
subject STRING COMMENT "学科"
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ","
STORED AS TEXTFILE;

2.上传数据

load data local inpath "/usr/local/soft/hive-3.1.2/data/student_20.txt" INTO TABLE learn3.student20;

3.实现需求

理科|男  1500100020|杭振凯,1500100019|娄曦之
---需求:将两列数据进行拼接 按照上面的格式存储输出

select
CONCAT(subject,"|",gender) as subject_gender
,CONCAT(name,"|",id) as name_id
from learn3.student20;

然后我们需要进行合并

select r.subject_gender,collect_list(r.name_id)
from
(
select
CONCAT(subject,"|",gender) as subject_gender
,CONCAT(name,"|",id) as name_id
from learn3.student20
) r group by subject_gender;

但是 我们如果想要达到需要的结果 我们还需要做一些其他操作 去掉两边的[ ] 我们对SQL语句做一下改进

select r.subject_gender,CONCAT_WS(",",collect_list(r.name_id))
from
(
select
CONCAT(subject,"|",gender) as subject_gender
,CONCAT(name,"|",id) as name_id
from learn3.student20
) r group by subject_gender;

对以上代码 我们也可以使用WITH AS写法

WITH concat_stu AS(
select
CONCAT(subject,"|",gender) as subject_gender
,CONCAT(name,"|",id) as name_id
from learn3.student20)
select concat_stu .subject_gender,CONCAT_WS(",",collect_list(concat_stu .name_id))
from concat_stu group by subject_gender;

| 文科|女            | ["1500100001|施笑槐","1500100007|尚孤风","1500100016|潘访烟","1500100018|骆怜雪"] |
| 文科|男            | ["1500100002|吕金鹏","1500100013|逯君昊"]                |
| 理科|女            | ["1500100003|单乐蕊","1500100005|宣谷芹","1500100008|符半双","1500100012|梁易槐","1500100015|宦怀绿","1500100017|高芷天"] |
| 理科|男            | ["1500100004|葛德曜","1500100006|边昂雄","1500100009|沈德昌","1500100010|羿彦昌","1500100011|宰运华","1500100014|羿旭炎","1500100019|娄曦之","1500100020|杭振凯"] |


desc function concat_ws;



| concat_ws(separator, [string | array(string)]+) - returns the concatenation of the strings separated by the separator. |

我们通过查看 可以看到 concat_ws()中的既可以是array类型的参数 也可以传入一个string类型的参数 所以我们可以使用concat_ws()函数用 , 号将它们拼接在一起 

4.行列互换

+-----------------+-----------------+
| subject_gender  |     id_name     |
+-----------------+-----------------+
| 文科|女            | 1500100001|施笑槐  |
| 文科|男            | 1500100002|吕金鹏  |
| 理科|女            | 1500100003|单乐蕊  |
| 理科|男            | 1500100004|葛德曜  |
| 理科|女            | 1500100005|宣谷芹  |
| 理科|男            | 1500100006|边昂雄  |
| 文科|女            | 1500100007|尚孤风  |
| 理科|女            | 1500100008|符半双  |
| 理科|男            | 1500100009|沈德昌  |
| 理科|男            | 1500100010|羿彦昌  |
| 理科|男            | 1500100011|宰运华  |
| 理科|女            | 1500100012|梁易槐  |
| 文科|男            | 1500100013|逯君昊  |
| 理科|男            | 1500100014|羿旭炎  |
| 理科|女            | 1500100015|宦怀绿  |
| 文科|女            | 1500100016|潘访烟  |
| 理科|女            | 1500100017|高芷天  |
| 文科|女            | 1500100018|骆怜雪  |
| 理科|男            | 1500100019|娄曦之  |
| 理科|男            | 1500100020|杭振凯  |



| 文科|女            | 1500100001|施笑槐,1500100007|尚孤风,1500100016|潘访烟,1500100018|骆怜雪 |
| 文科|男            | 1500100002|吕金鹏,1500100013|逯君昊                      |
| 理科|女            | 1500100003|单乐蕊,1500100005|宣谷芹,1500100008|符半双,1500100012|梁易槐,1500100015|宦怀绿,1500100017|高芷天 |
| 理科|男            | 1500100004|葛德曜,1500100006|边昂雄,1500100009|沈德昌,1500100010|羿彦昌,1500100011|宰运华,1500100014|羿旭炎,1500100019|娄曦之,1500100020|杭振凯 |

1)行转列:
    

将原先多行数据转成一行

转换方式:   

通过COLLECT_SET() 或者 COLLECT_LIST() 和 GROUP BY 进行配合使用     

将GROUP BY 分组的数据进行存放于一个集合当中


2)列传行:

将一行数据转换为多行数据   

①如何转换:(案例)
案例:
| wordcount.word  |
+-----------------+
| hello,word      |
| hello,java      |
| hello,hive      |
| hello,word      |
| hello,java      |
| hive,hello      |

结果:
+----------+
| _u1.col  |
+----------+
| hello    |
| hive     |
| java     |
| word     |
| hello    |
| hive     |
+----------+

如果是这种格式一致的表 我们在进行列转行的操作时 可以使用拼接的方式

WITH split_res AS
(
select split(word,",")[0] as clo1,
split(word,",")[1] as clo2
from learn3.wordcount
)
,c1 AS
(
select clo1 as clo,count(*) as num
from split_res group by clo1
)
,c2 AS
(
select clo2 as clo,count(*) as num
from split_res group by clo2
)
select clo from c1
UNION ALL
select clo from c2;

现在我们的数据参差不齐 刚才的方法就没办法使用了 那么 有没有什么更方便的方法呢?

我们再插入一行数据

INSERT INTO TABLE learn3.wordcount (word) VALUES ("hello,word,hello,java,hello,spark");

②EXPLODE() 函数:将集合中的一行数据转换为多行
select
EXPLODE(split(word,",")) as word
FROM learn3.wordcount;

现在我们再对这个表做wordcount也就非常方便了 直接使用count和group by就可以了

select count(a.word) as num,a.word
from
(
select
EXPLODE(split(word,",")) as word
FROM learn3.wordcount
) a group by a.word;

③示例2:增加一列数据

CREATE TABLE learn3.movie(
movie_name STRING COMMENT "电影名",
types STRING COMMENT "电影类型"
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE;

load data local inpath "/usr/local/soft/hive-3.1.2/data/moive.txt" INTO TABLE learn3.movie;

需求:

---- 将types列中的电影类型进行分隔,并且与电影名进行对应
由  |肖申克的救赎            | 犯罪/剧情        |  
转换为:
  肖申克的救赎 犯罪
  肖申克的救赎 剧情


如果我们直接使用查询语句 我们会发现报下面的错误 因为我们现在多了一列数据 他怎么实现对应 这是一个问题

select movie_name
,EXPLODE(split(types,"/")) as type
FROM learn3.movie;

lateral view 用法:行转列

我们根据示例修改一下我们的SQL语句

select
movie_name,type
from learn3.movie LATERAL VIEW EXPLODE(split(types,"/")) view as type;



| movie.movie_name  | movie.types  |
+-------------------+--------------+
| 肖申克的救赎            | 犯罪/剧情        |
| 霸王别姬              | 剧情/爱情/同性     |
| 阿甘正传              | 剧情/爱情        |
| 泰坦尼克号             | 剧情/爱情/灾难     |
| 这个杀手不太冷           | 剧情/动作/犯罪     |


| movie_name  | type  |
+-------------+-------+
| 肖申克的救赎      | 犯罪    |
| 肖申克的救赎      | 剧情    |
| 霸王别姬        | 剧情    |
| 霸王别姬        | 爱情    |
| 霸王别姬        | 同性    |
| 阿甘正传        | 剧情    |
| 阿甘正传        | 爱情    |
| 泰坦尼克号       | 剧情    |
| 泰坦尼克号       | 爱情    |
| 泰坦尼克号       | 灾难    |
| 这个杀手不太冷     | 剧情    |
| 这个杀手不太冷     | 动作    |
| 这个杀手不太冷     | 犯罪    |

LATERAL VIEW EXPLODE(split(types,"/")) view as type

解析:  

① 通过split方法将types中的字符串切分为数组

② 通过EXPLODE方法将数组由一行数据转换为多行

③ 通过LATERAL VIEW 将EXPLODE转换的结果包装成一个名为view的一个侧写表,并且列名为type
④ 通过全连接将侧写表中的数据与原表 learn3.movie 中的一行数据进行全连接 

  • 25
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hive中没有直接的行列互换函数,但可以通过以下方式实现: 1. 使用CASE WHEN语句将列转换为行 例如,假设有以下表格: ``` id | name | age | gender -----|------|-----|------- 1 | Alice| 25 | F 2 | Bob | 30 | M 3 | Chris| 27 | M ``` 我们想要将它转换为以下形式: ``` field | 1 | 2 | 3 -------|------|------|------ name | Alice| Bob | Chris age | 25 | 30 | 27 gender | F | M | M ``` 可以使用以下查询语句: ``` SELECT 'name' AS field, MAX(CASE WHEN id = 1 THEN name END) AS 1, MAX(CASE WHEN id = 2 THEN name END) AS 2, MAX(CASE WHEN id = 3 THEN name END) AS 3 FROM my_table UNION ALL SELECT 'age' AS field, MAX(CASE WHEN id = 1 THEN age END) AS 1, MAX(CASE WHEN id = 2 THEN age END) AS 2, MAX(CASE WHEN id = 3 THEN age END) AS 3 FROM my_table UNION ALL SELECT 'gender' AS field, MAX(CASE WHEN id = 1 THEN gender END) AS 1, MAX(CASE WHEN id = 2 THEN gender END) AS 2, MAX(CASE WHEN id = 3 THEN gender END) AS 3 FROM my_table; ``` 2. 使用LATERAL VIEW EXPLODE函数将行转换为列 假设有以下表格: ``` id | category | value -----|----------|------ 1 | A | 10 1 | B | 20 1 | C | 30 2 | A | 40 2 | B | 50 2 | C | 60 ``` 我们想要将它转换为以下形式: ``` id | A | B | C -----|---|---|--- 1 | 10| 20| 30 2 | 40| 50| 60 ``` 可以使用以下查询语句: ``` SELECT id, MAX(CASE WHEN category = 'A' THEN value END) AS A, MAX(CASE WHEN category = 'B' THEN value END) AS B, MAX(CASE WHEN category = 'C' THEN value END) AS C FROM my_table LATERAL VIEW EXPLODE(array('A', 'B', 'C')) exploded_table AS category GROUP BY id; ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值