当前位置: 首页 > news >正文

【Hive SQL 每日一题】行列转换

文章目录

    • 行转列
    • 列传行

行转列

测试数据:

DROP TABLE IF EXISTS student_scores;CREATE TABLE student_scores (student_id INT,subject STRING,score INT
);INSERT INTO student_scores (student_id, subject, score) VALUES
(1, 'Math', 85),
(1, 'English', 78),
(1, 'Science', 92),
(2, 'Math', 88),
(2, 'English', 76),
(2, 'Science', 81),
(3, 'Math', 90),
(3, 'English', 82),
(3, 'Science', 89);

表的结构以及数据展示如下:

student_idsubjectscore
1Math85
1English78
1Science92
2Math88
2English76
2Science81
3Math90
3English82
3Science89

根据上面的学生成绩表,将其中的行转换成列进行展示,如下所示:

student_idmathenglishscience
1857892
2887681

这个需求主要从两个方面切入:

  • 因为是统计每名学生的成绩,所以按学生进行分组。

  • 行转列操作,其实就是将行数据通过列的方式进行查询展示而已,这里将行转为列的数据共有 3 列,分别代表每名同学各科的成绩,我们只需要在统计时加入判断条件即可,每列固定求某科的成绩,如果不是该科则用 0 或者空值替代,这样就可以轻松完成需求啦。

selectstudent_id,sum(if(subject="Math",score,0)) math,sum(if(subject="English",score,0)) english,sum(if(subject="Science",score,0)) science
fromstudent_scores
group bystudent_id;

输出结果如下:

在这里插入图片描述

列传行

现在变换一下需求,将学生成绩表中的数据列转换为行,测试数据:

DROP TABLE IF EXISTS student_scores_pivoted;
CREATE TABLE student_scores_pivoted (student_id INT,math INT,english INT,science INT
);INSERT INTO student_scores_pivoted VALUES
(1, 85, 78, 92),
(2, 88, 76, 81),
(3, 90, 82, 89);

表的结构以及数据展示如下:

student_idMathEnglishScience
1857892
2887681
3908289

我们需要将其转换为如下结构:

student_idsubjectscore
1Math85
1English78
1Science92
2Math88
2English76
2Science81
3Math90
3English82
3Science89

这里使用到了 lateral view + posexplode 的方式,将表的一列扩展到多行,从而完成列转行的需求。

相较于传统的 lateral view + explode 扩展方式,posexplode 会返回两个参数,其中第一个参数表示索引,第二个参数才是其对应的值。

selectstudent_id,subject_name_list,subject_list
from(selectstudent_id,concat_ws(',',"Math","English","Science") subject_name,concat_ws(',',cast(math as string),cast(english as string),cast(science as string)) subjectfromstudent_scores_pivoted)t1 lateral view posexplode(split(subject,",")) tmp1 as pos1,subject_listlateral view posexplode(split(subject_name,",")) tmp2 as pos2,subject_name_list
wheretmp1.pos1 = tmp2.pos2;

输出结果如下:

在这里插入图片描述

explodeposexplode 的区别:

-- explode 主要用于将一个包含多个元素的列转换为多行,每行对应一个元素。
SELECT explode(array(1, 2, 3));
-- 结果为:
1
2
3-- posexplode 与 explode 类似,但它不仅返回数组中的值,还返回值在数组中的位置(索引)。
SELECT posexplode(array(1, 2, 3));
-- 结果为:
0  1
1  2
2  3

那么这里为什么使用 posexplode 而不是 explode 呢?

如果在这里使用 explode,那么会导致扩张多次(因为在这里使用了两次 explode3*3 最终会将每行扩张 9 次,形成笛卡尔积),变成如下所示的结果:

在这里插入图片描述

所以在这里并不使用 explode,推荐使用另一个函数 posexplode,虽然它也会导致笛卡尔积,但可以根据索引设置条件进行过滤:

在这里插入图片描述

下面将来讲述这些笛卡尔积数据产生的原因,以及过滤条件该如何设置。

在只使用一个扩展函数时,并不会产生笛卡尔积,如下所示:

在这里插入图片描述

如果同时使用两个扩展函数,那么就会产生笛卡尔积,会随着后续每行的数据量成倍数增长,如下所示:

在这里插入图片描述

在使用 posexplode 函数形成笛卡尔积后,我们可以通过设置 where 条件来进行过滤,取到对应的数据。

通过观察可以发现,只有当两个索引列的值相同时,其扩展的数据行才是正确的,我们可以通过这一特性来对数据进行过滤,获取最终的结果:

在这里插入图片描述

其实,列转行还有其它的写法,这里提供另一种更容易理解的思路:

  • 先通过子查询获取单科的成绩;

  • 然后再进行合并。

如下所示:

selectstudent_id,"math" subject_name,math score
fromstudent_scores_pivoted
union all
selectstudent_id,"english" subject_name,english score
fromstudent_scores_pivoted
union all
selectstudent_id,"science" subject_name,science score
fromstudent_scores_pivoted;

输出结果如下:

在这里插入图片描述

解决问题的方式有许多种,但往往我们需要去注重学习解决问题的思路,希望本文对你有所帮助。

相关文章:

  • Centos 停服倒计时!你的操作系统何去何从?
  • C++小病毒
  • 正则项学习笔记
  • Windows:iHasher-v0.2安装报错Windows 功能 .NET Framework 3.5
  • 2024年 电工杯 (A题)大学生数学建模挑战赛 | 园区微电网风光储协调优化配置 | 数学建模完整代码解析
  • 【ChatGPT】 Microsoft Edge 浏览器扩展使用 GPT
  • 【会议征稿,IEEE独立出版】第四届计算机技术与信息科学国际研讨会(ISCTIS 2024)
  • Java面试八股之有哪些线程安全的集合类
  • 【晶体拆解】Quartz MEMS Oscillator
  • 【Java】手把手学会数组的使用
  • react使用AntV
  • IPD在卷烟工业企业研发管理中应用
  • 深入 Rust 标准库,Rust标准库源代码系统分析
  • YOLOv8实例分割离线数据增强,标签可视化!
  • 切换分支报错:Untracked Files Prevent Checkout
  • C++类的相互关联
  • Date型的使用
  • Docker 笔记(2):Dockerfile
  • Linux各目录及每个目录的详细介绍
  • Linux链接文件
  • mysql 数据库四种事务隔离级别
  • RxJS: 简单入门
  • Spring Boot快速入门(一):Hello Spring Boot
  • Spring Cloud中负载均衡器概览
  • Yeoman_Bower_Grunt
  • 初探 Vue 生命周期和钩子函数
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 工作中总结前端开发流程--vue项目
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 学习ES6 变量的解构赋值
  • 用 Swift 编写面向协议的视图
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • !$boo在php中什么意思,php前戏
  • #1014 : Trie树
  • #Datawhale X 李宏毅苹果书 AI夏令营#3.13.2局部极小值与鞍点批量和动量
  • #include
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • $.ajax,axios,fetch三种ajax请求的区别
  • (1)Android开发优化---------UI优化
  • (C++20) consteval立即函数
  • (第61天)多租户架构(CDB/PDB)
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转)Windows2003安全设置/维护
  • .NET DataGridView数据绑定说明
  • .NET Reactor简单使用教程
  • .NET开发不可不知、不可不用的辅助类(一)
  • .net中应用SQL缓存(实例使用)
  • @JsonFormat与@DateTimeFormat注解的使用
  • @拔赤:Web前端开发十日谈
  • [20170713] 无法访问SQL Server
  • [Algorithm][综合训练][体育课测验(二)][合唱队形][宵暗的妖怪]详细讲解
  • [Android]通过PhoneLookup读取所有电话号码