Hive SQL中的 lateral view 与 explode(列转行)以及行转列

2023-12-28 09:20

本文主要是介绍Hive SQL中的 lateral view 与 explode(列转行)以及行转列,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、列转行
    • Explode炸裂函数
      • posexplode()函数
    • Lateral View
    • 例子1
    • 例子2
    • 例子3
    • 例子4——多列炸裂 Posexplode
    • 例子5
    • 例子6
  • 二、行转列
    • 例子1
    • 例子2

一、列转行

行转列:将多个列中的数据在一列中输出
列转行:将某列一行中的数据拆分成多行

Explode炸裂函数

将hive某列一行中复杂的 array 或 map 结构拆分成多行(只能输入array或map)

语法

explode(col)
select explode(arraycol) as newcol from tablename;

explode():函数中的参数传入的是arrary数据类型的列名。

newcol:是给转换成的列命名一个新的名字,用于代表转换之后的列名。

tablename:原表名


explode(array)使得结果中将array列表里的每个元素生成一行

// 输入是array时,array中的每个元素都单独输出为一行
select(array('1','2','3')) 

explode(map)使得结果中将map里的每一对元素作为一行,key为一列,value为一列,

select explode(map('A','1','B','2','C','3'))

在这里插入图片描述

通常,explode函数会与lateral view一起结合使用

posexplode()函数

对一列进行炸裂可以使用 explode()函数,但是如果想实现对两列都进行多行转换,那么用explode()函数就不能实现了,可以用posexplode()函数,因为该函数可以将index和数据都取出来,使用两次posexplode并令两次取到的index相等就行了。

详见例子4和例子5

Lateral View

Lateral View配合 split, explode 等UDTF函数一起使用,它能够将一列数据拆成多行数据,并且对拆分后结果进行聚合,即将多行结果组合成一个支持别名的虚拟表

语法

lateral view udtf(expression) tableAlias as columnAlias (,columnAlias)*

lateral view在UDTF前使用,表示连接UDTF所分裂的字段。

UDTF(expression):使用的UDTF函数,例如explode()。

tableAlias:表示UDTF函数转换的虚拟表的名称。

columnAlias:表示虚拟表的虚拟字段名称,如果分裂之后有一个列,则写一个即可;如果分裂之后有多个列,按照列的顺序在括号中声明所有虚拟列名,以逗号隔开。


Lateral View主要解决在select使用UDTF做查询的过程中查询只能包含单个UDTF,不能包含其它字段以及多个UDTF的情况(不能添加额外的select列的问题)。

Lateral View其实就是用来和想类似explode这种UDTF函数联用的,lateral view会将UDTF生成的结果放到一个虚拟表中,然后这个虚拟表会和输入行进行join来达到连接UDTF外的select字段的目的。

引用:hive中的lateral view 与 explode函数的使用
在这里插入图片描述

注:
1)lateral view的位置是from后where条件前
2)生成的虚拟表的表名不可省略
3)from后可带多个lateral view
3)如果要拆分的字段有null值,需要使用lateral view outer 替代,避免数据缺失

例子1

假设有如下movies表,字段名分别为movie(string)category(array<string>)
在这里插入图片描述
转换为

在这里插入图片描述

select movie,category_name
from  movies 
lateral view explode(category) table_tmp as category_name;-- 结果:
--《疑犯追踪》	悬疑
--《疑犯追踪》	动作
--《疑犯追踪》	科幻
--《疑犯追踪》	剧情
--《海豹突击队》	动作
-- ...

注:explode函数输入了一个string类型的参数,搭配split()函数


例子2

a       b       1,2,3
c       d       4,5,6

转换为

a       b       1
a       b       2
a       b       3
c       d       4
c       d       5
c       d       6
select col1, col2, col5
from test
lateral view explode(split(col3,','))  b AS col5
// split(col3,",")相对字符串切割,得到数组

注:explode函数输入了一个string类型的参数,搭配split()函数

例子3

应用文章的一个思考题
掌握这个SQL技巧超越80%的人——行转列/列转行

在这里插入图片描述

select uid_split, game 
from ( select uid,gamefrom user_gamelateral view explode(split(game_list,",")) tmpTable as game
) a
lateral view explode(split(uid, ",")) m as uid_split

例子4——多列炸裂 Posexplode

前面提到:

对一列进行炸裂可以使用 explode()函数,但是如果想实现对两列都进行多行转换,那么用explode()函数就不能实现了,可以用posexplode()函数,因为该函数可以将index和数据都取出来,使用两次posexplode并令两次取到的index相等就行了。

引用例子来自:Hive中的explode使用全解

在这里插入图片描述
单列Posexplode

selectclass,student_index + 1 as student_index,student_name
fromdefault.classinfolateral view posexplode(split(student,',')) t as student_index,student_name;

在这里插入图片描述

双列炸裂,转换成如下的形式

在这里插入图片描述

注:不能这样用!

select class,student_name,student_score
from default.classinfo
lateral view explode(split(student,',')) sn as student_name
lateral view explode(split(score,',')) sc as student_score

这样写的结果如下,不符合需求

在这里插入图片描述

可以进行两次posexplode,姓名和成绩都保留对应的序号,即使变成了9行,也通过where条件只保留序号相同的行即可。
select class,student_name,student_score
from default.classinfolateral view posexplode(split(student,',')) sn as student_index_sn,student_namelateral view posexplode(split(score,',')) sc as student_index_sc,student_score
wherestudent_index_sn = student_index_sc;

例子5

引用例子来自:https://blog.csdn.net/dzysunshine/article/details/101110467

在这里插入图片描述

转换成如下形式

single_id  single_tim
a			2:00
b			3:00
c			4:00
d			5:00
f			1:10
b			2:20
c			3:30
d			4:40

一次posexplode

select id,tim,single_id_index,single_id 
from test.a 
lateral view posexplode(split(id,',')) t as single_id_index, single_id;d;

结果

single_id_index		single_id
0					a
1					b
2					c
3					d
0					f
1					b
2					c
3					d

两次posexplode+where筛选

select id,tim,single_id,single_tim 
from test.a lateral view posexplode(split(id,',')) t as single_id_index, single_idlateral view posexplode(split(tim,',')) t as single_yim_index, single_tim
where single_id_index = single_yim_index;

例子6

在这里插入图片描述

select column1, column2, column3, m_key, m_val from(select column1, column2, column3, map("X1", X1, "X2", X2, "X3", X3, "X4", X4) as map1from table1) as t1
lateral view explode(map1) xyz as m_key, m_val    

二、行转列

行转列:将多个列中的数据在一列中输出
列转行:将某列一行中的数据拆分成多行


Concat

concat(string1/col, string2/col,)

输入任意个字符串(或字段,可以为int类型等),返回拼接后的结果

select concat(id,'-',name,'-',age) 
from student;

Concat_ws

concat_ws(separator, str1, str2,)

特殊形式的 concat(),参数只能为字符串,第一个参数为后面参数的分隔符

分隔符可以是与后面参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;

select concat_ws('-', name, gender) 
from student;

Collect_set(聚合,返回数组类型)

collect_set(col)

将某字段进行去重处理返回array类型;该函数只接受基本数据类型

select collect_set(age) 
from student;

collect_set 与 collect_list 的区别就是set去重,list不去重


例子1

把星座和血型一样的人归类到一起
在这里插入图片描述
结果

射手座,A            大海|凤姐
白羊座,A            孙悟空|猪八戒
白羊座,B            宋宋
selectt1.base,concat_ws('|', collect_set(t1.name)) as name
from(select name,concat(constellation, ",", blood_type) as basefrom person_info) as t1
group byt1.base;

例子2

在这里插入图片描述
结果:

张三    语文,数学,英语   98,95,89
李四    语文,数学,英语   97,88,90
select stu_name,concat_ws(',',collect_set(course)) as course,concat_ws(',',collect_set(score)) as score
from student
group by stu_name

另外,行转列常用函数还有

case when <expr> then <result>else <default> end
if(expr, true_result, false_result)

case when 语句是SQL中的一个非常重要的功能,可以完成很多复杂的计算,相当于一个表达式,可以放在任何可放表达式的地方。

语法 case when 条件 then 结果 when 条件 then 结果 else end。else可不加,是缺省条件下的值,如果不加,有缺省情况则为NULL。CASE WHEN还可以和GROUP BY 语句搭配使用,用在sum,count,max等聚合函数内部。

在这里插入图片描述

详情参见文章掌握这个SQL技巧超越80%的人——行转列/列转行

参考:
Hive SQL中的lateral view explode
https://zhuanlan.zhihu.com/p/142666980

这篇关于Hive SQL中的 lateral view 与 explode(列转行)以及行转列的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/545512

相关文章

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要

mysql出现ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)的解决方法

《mysql出现ERROR2003(HY000):Can‘tconnecttoMySQLserveron‘localhost‘(10061)的解决方法》本文主要介绍了mysql出现... 目录前言:第一步:第二步:第三步:总结:前言:当你想通过命令窗口想打开mysql时候发现提http://www.cpp

MySQL大表数据的分区与分库分表的实现

《MySQL大表数据的分区与分库分表的实现》数据库的分区和分库分表是两种常用的技术方案,本文主要介绍了MySQL大表数据的分区与分库分表的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. mysql大表数据的分区1.1 什么是分区?1.2 分区的类型1.3 分区的优点1.4 分

MySQL错误代码2058和2059的解决办法

《MySQL错误代码2058和2059的解决办法》:本文主要介绍MySQL错误代码2058和2059的解决办法,2058和2059的错误码核心都是你用的客户端工具和mysql版本的密码插件不匹配,... 目录1. 前置理解2.报错现象3.解决办法(敲重点!!!)1. php前置理解2058和2059的错误

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

MySQL INSERT语句实现当记录不存在时插入的几种方法

《MySQLINSERT语句实现当记录不存在时插入的几种方法》MySQL的INSERT语句是用于向数据库表中插入新记录的关键命令,下面:本文主要介绍MySQLINSERT语句实现当记录不存在时... 目录使用 INSERT IGNORE使用 ON DUPLICATE KEY UPDATE使用 REPLACE

MySQL Workbench 安装教程(保姆级)

《MySQLWorkbench安装教程(保姆级)》MySQLWorkbench是一款强大的数据库设计和管理工具,本文主要介绍了MySQLWorkbench安装教程,文中通过图文介绍的非常详细,对大... 目录前言:详细步骤:一、检查安装的数据库版本二、在官网下载对应的mysql Workbench版本,要是

mysql数据库重置表主键id的实现

《mysql数据库重置表主键id的实现》在我们的开发过程中,难免在做测试的时候会生成一些杂乱无章的SQL主键数据,本文主要介绍了mysql数据库重置表主键id的实现,具有一定的参考价值,感兴趣的可以了... 目录关键语法演示案例在我们的开发过程中,难免在做测试的时候会生成一些杂乱无章的SQL主键数据,当我们