hive实现行转列

229 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

在日常数据开发过程中,经常需要将行数据转换为列数据,故汇总了最近开发的一个数据需求涉及到的技术,下面将需求简化描述,其中实现的逻辑还是一样的。

需求:现在有一张学生的课程成绩表,其中包含学生id、课程类型、课程名称、成绩等等字段。

现在需要将这张课程成绩表中的行转成列,其中列名是包括了学生id,需要的数据是语文、数学、英语三门课程的成绩,以及这三门课程的汇总成绩。

select student_code, 
  temp[1] yuwen_grade,
  temp[2] shuxue_grade,
  temp[3] yingyu_grade,
 from (
  select student_code, str_to_map(concat_ws(',', collect_set(concat(maintain_type, '-', maintain_name))),',','-') temp
    from (
    select student_code, maintain_type, maintain_name
    from student_subject_grade_desc
      where pt='20220507000000' and maintain_type in (1,2,3) and student_code >100000
    group by student_code, maintain_type, maintain_name
  ) tmp
   group by student_code
 ) t

这里的核心技术就是通过将每一行的数据收集到一个json串之中,然后通过type为索引,分别取出索引对应的值,作为新的列。将行数据收集到一个json串里应用到了collect_set()函数、concat_ws()函数和str_to_map()函数。

concat_ws()函数就不解释了,之前详细介绍过,就是在字符串中加上分隔符。

下面解释一下这个函数的用法:

collect_set()函数 作用:收集多个字段为一个字段

常见使用方法:collect_set()

具体功能描述:这个是行转列的专用函数之一,可以将符合满足条件的行内容合并到一个数组中,并通过制定的字段分组汇总。

select 
  id,collect_set(a)
from 
(select id,a from tmp.testone where 1=1) group by id;
​
​
>> ['aa','bb']
​

str_to_map()函数 作用:将字符串按照分隔符转换为map

常见使用方法:str_to_map()

具体功能描述:将字符串按照指定的符号分隔开,并组合成map

select str_to_map('aaa-11,bbb-22', ',', '-')
  from tmp.testtwo;
​
​
>> {"bbb":"22","aaa":"11"}

想要实现行转列当然还有其他很多方式,比如用一张临时表作为中间表,将明细数据横向拉出来,并且标记上顺序1、2、3、4、5...然后再新建一张表根据标签依次取出数据,塞入到纵向列表中即可。如果大家感兴趣后面我会着重介绍一篇这样的实现方式。