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

Hive SQL 之 `LATERAL VIEW EXPLODE` 的正确打开方式

一文彻底搞懂 LATERAL VIEW EXPLODE

1. 引言

在处理复杂数据结构(如数组、映射)时,Hive SQL 提供了强大的功能来简化查询和数据分析。其中,LATERAL VIEWEXPLODE 是两个特别有用的关键字,它们可以帮助我们将复杂的数据类型拆分成更易处理的行格式。本文将详细介绍 LATERAL VIEW EXPLODE 的概念、应用场景以及具体使用方法。


2. 概念定义

LATERAL VIEW
  • 定义LATERAL VIEW 是 Hive SQL 中用于结合表生成函数(Table Generating Functions, TGFs)的一个关键字。它允许我们在同一个查询中对一个表执行额外的操作,例如调用 EXPLODE 函数。
  • 作用:通过 LATERAL VIEW,我们可以为每个输入行生成多个输出行,并将这些新生成的行与原始数据合并,形成一个新的结果集。
EXPLODE
  • 定义EXPLODE 是一种表生成函数,它接收一个数组或映射作为输入,并为输入中的每一个元素生成一行输出。
  • 特点:如果输入是一个数组,则每一行代表数组中的一个元素;如果是映射,则每一行包含键值对中的一个键及其对应的值。
LATERAL VIEW EXPLODE
  • 组合使用LATERAL VIEW EXPLODE 组合使用时,可以将复杂的数据结构(如数组或映射)转换成多行记录,使得原本难以处理的数据变得更加直观和易于分析。
  • 好处:简化了对复杂数据类型的查询逻辑,提高了查询效率和灵活性。

3. 语法详解

语法结构
LATERAL VIEW [OUTER] EXPLODE(column) alias AS column_name
  • LATERAL VIEW:这是必须的关键词,表示接下来要应用一个表生成函数。
  • [OUTER]:可选关键词。默认情况下,EXPLODE 只会处理非空数组或映射。如果你希望保留原表中的所有行,即使某些行的指定列为空或为 NULL,可以使用 OUTER 关键词。
  • EXPLODE(column):这是实际的表生成函数,column 表示你要展开的数组或映射列名。
  • alias:给由 EXPLODE 操作产生的临时结果集起一个别名。这有助于在外层查询中引用这些新生成的行。
  • AS column_name:为 EXPLODE 操作后的新列命名。这个新列将包含从原数组或映射中提取出来的单个元素。
示例语法

假设有一个表 users,其中有一列 hobbies 是一个数组:

SELECT id, hobby
FROM users
LATERAL VIEW EXPLODE(hobbies) exploded_hobbies AS hobby;

在这个例子中:

  • LATERAL VIEW 表示我们将在当前查询上下文中引入一个表生成函数。
  • EXPLODE(hobbies)hobbies 数组中的每个元素都转换成一行新的 hobby 列。
  • exploded_hobbies 是给由 EXPLODE 操作产生的结果集起的别名。
  • AS hobby 定义了新生成的列名为 hobby
使用 OUTER 关键词

如果你想确保即使 hobbies 列为空或为 NULL 的行也保留在结果集中,可以使用 OUTER 关键词:

SELECT id, hobby
FROM users
LATERAL VIEW OUTER EXPLODE(hobbies) exploded_hobbies AS hobby;

4. 使用场景

LATERAL VIEW EXPLODE 在以下场景中尤为有用:

  • 从数组或映射中提取信息:当你有一个包含多个值的数组或映射列,并希望将这些值展开成独立的行进行进一步分析时。
  • 处理嵌套数据结构:对于存储在 JSON 或其他嵌套格式中的数据,可以通过 EXPLODE 来扁平化这些结构,便于后续操作。
  • 聚合复杂数据:当需要对复杂数据类型中的元素进行统计或聚合时,EXPLODE 可以帮助你将这些元素拆分出来,方便计算。

5. 实际应用案例

案例1:数组直接展开

假设我们有一个日志表 logs,其中有一列 tags 存储的是用户标签的数组,如下所示:

idtags
1[‘admin’, ‘user’]
2[‘user’]

我们想要知道每个标签出现的次数。这时就可以使用 LATERAL VIEW EXPLODE

SELECT tag, COUNT(*) as count
FROM logs
LATERAL VIEW EXPLODE(tags) exploded_tags AS tag
GROUP BY tag;

这段代码会将 tags 数组中的每个元素都转换成一行新的 tag 列,并统计每个标签的出现次数。结果可能如下:

tagcount
admin1
user2

案例2:先加工成数组,再展开

在实际的数据处理中,有时我们会遇到以逗号分隔的字符串(CSV 格式),例如一个用户的兴趣爱好可能被存储为一个逗号分隔的字符串。为了更好地分析这些数据,我们可以先使用 SPLIT 函数将字符串转换成数组,然后再用 LATERAL VIEW EXPLODE 将这个数组展开成多行。

假设我们有一个表 users,其中有一列 interests 存储的是用户兴趣爱好的逗号分隔字符串,如下所示:

idnameinterests
1Alicemusic,books
2Bobsports,games,books

我们想要将每个用户的兴趣爱好单独列出,并统计每个兴趣爱好的出现次数。可以按照以下步骤进行操作:

步骤 1: 使用 SPLIT 函数生成数组

首先,我们需要将 interests 列中的逗号分隔字符串转换成数组。这可以通过 SPLIT 函数实现,该函数接收一个字符串和一个分隔符作为参数,并返回一个数组。

SELECT id, name, SPLIT(interests, ',') as interest_array
FROM users;

这段代码会将 interests 列中的每个逗号分隔字符串转换成一个数组 interest_array

步骤 2: 使用 LATERAL VIEW EXPLODE 展开数组

接下来,我们将使用 LATERAL VIEW EXPLODE 来将 interest_array 数组中的每个元素都转换成一行新的 interest 列。

SELECT id, name, interest
FROM (
  SELECT id, name, SPLIT(interests, ',') as interest_array
  FROM users
) t
LATERAL VIEW EXPLODE(interest_array) exploded_interests AS interest;

在这段代码中:

  • 内层查询将 interests 列中的逗号分隔字符串转换成了数组 interest_array
  • LATERAL VIEW EXPLODE(interest_array) 将数组中的每个元素都转换成一行新的 interest 列。
  • exploded_interests 是给由 EXPLODE 操作产生的结果集起的别名。
  • AS interest 定义了新生成的列名为 interest

执行上述查询后,结果将会是:

idnameinterest
1Alicemusic
1Alicebooks
2Bobsports
2Bobgames
2Bobbooks
步骤 3: 统计每个兴趣爱好的出现次数

最后,我们可以对展开后的兴趣爱好进行统计,计算每个兴趣爱好的出现次数:

SELECT interest, COUNT(*) as count
FROM (
  SELECT id, name, SPLIT(interests, ',') as interest_array
  FROM users
) t
LATERAL VIEW EXPLODE(interest_array) exploded_interests AS interest
GROUP BY interest;

这段代码会统计每个兴趣爱好的出现次数,结果可能是:

interestcount
music1
books2
sports1
games1

6. 操作层面

  1. 准备数据:确保你的表中包含至少一列是数组或映射类型,或者是一个逗号分隔的字符串。
  2. 编写查询
    • 如果是逗号分隔的字符串,使用 SPLIT 函数将其转换成数组。
    • 使用 LATERAL VIEW 关键字引入 EXPLODE 操作。
    • 指定要展开的数组或映射列名。
    • 使用 AS 关键字为新生成的列命名。
  3. 执行查询:运行你的查询语句,查看由 EXPLODE 产生的新行。
  4. 分析结果:根据需要对生成的新行进行进一步的筛选、排序或聚合操作。

示例代码:

-- 将 users 表中 interests 字段的逗号分隔字符串转换成数组并展开成多行
SELECT id, name, interest
FROM (
  SELECT id, name, SPLIT(interests, ',') as interest_array
  FROM users
) t
LATERAL VIEW EXPLODE(interest_array) exploded_interests AS interest;

7. 常见问题与解决方案

  • 问题LATERAL VIEW EXPLODE 后,原始列不见了怎么办?

    • 解决方案:在外层 SELECT 语句中明确指定你需要的所有列,包括原始列和新生成的列。你可以使用子查询别名来引用原始列,如 t.interest,还是来举个🌰:

      SELECT t.id, t.name, t.interest,exploded_interests.interest_new
      FROM (
       SELECT id, name, SPLIT(interests, ',') as interest_array
       FROM users
      ) t
      LATERAL VIEW EXPLODE(t.interest_array) exploded_interests AS interest_new;
      

      当然,当你explode后生成的字段和原始字段本身就不冲突时,可以忽略掉表名,简化如下:

      SELECT t.id, t.name, interest, interest_new
      FROM (
        SELECT id, name, SPLIT(interests, ',') as interest_array
        FROM users
      ) t
      LATERAL VIEW EXPLODE(t.interest_array) exploded_interests AS interest_new;
      

      一般给出的示例代码都是下面这样的,这样在外层 SELECT 的时候,EXPLODE 新生成 interests 就会把内层的 interests 给覆盖掉,导致内层的 interests 不见了,这样主要是为了简化写法,从使用角度当然是没问题的,这个地方其实丢掉了内层原始 interests 字段;这个地方涉及到变量作用域的问题,展开说其实有点多,有心的同学这个地方可以稍微注意一下!!!

      SELECT t.id, t.name, interest, interest_new
      FROM (
        SELECT id, name, SPLIT(interests, ',') as interest_array
        FROM users
      ) subquery
      LATERAL VIEW EXPLODE(t.interest_array) subquery AS interests;
      
  • 问题:如何处理空数组或 NULL 值?

    • 解决方案EXPLODE 函数会跳过空数组或 NULL 值,不会产生任何新行。如果你需要保留这些行,可以在 LATERAL VIEW 后添加 OUTER 关键字,例如 LATERAL VIEW OUTER EXPLODE(...)

8. 总结

LATERAL VIEW EXPLODE 是 Hive SQL 中处理复杂数据结构的强大工具,它能够将数组或映射等复杂类型转换成易于处理的行格式。通过本文的学习,你应该已经掌握了它的基本概念、应用场景及具体的使用方法。实践是最好的老师,尝试将这些知识应用于实际工作中,你会发现它极大地提升了数据处理的效率和灵活性。


http://www.kler.cn/a/455650.html

相关文章:

  • Windows配置cuda,并安装配置Pytorch-GPU版本
  • Wend看源码-Java-集合学习(List)
  • React 高级组件开发:动态逻辑与性能优化
  • linux ext4文件系统
  • 【速成51单片机】1.已经学过stm32如何快速入门51单片机——软件下载与安装
  • STM32开发笔记123:使用STM32CubeProgrammer下载程序
  • DS的使用
  • StarRocks 排查单副本表
  • Kotlin 语言基础语法及标准库
  • [2029].第6-06节:MyISAM引擎中的索引与 InnoDB引擎中的索引对比
  • C# 线程安全集合
  • 阿里云技术公开课:基于阿里云 Elasticsearch 构建 AI 搜索和可观测 Chatbot
  • 计算机故障找不到x3daudio1_7.dll怎么解决?
  • C#开发实例2—模拟考试
  • Jsonlizer,一个把C++各类数据转成 Json 结构体的玩意儿
  • asp.net core系统记录当前在线人数
  • 组建基于IPV6的网络
  • 更新本地项目到最新git版本脚本
  • 每天40分玩转Django:Django Email
  • 微服务网关路由
  • node.js高级用法
  • LeetCode -Hot100 - 56. 合并区间
  • 【centos8 镜像修改】centos8 镜像修改阿里云
  • c++编译过程初识
  • 【Java 代码审计入门-03】XSS 漏洞原理与实际案例介绍
  • MFC扩展库BCGControlBar Pro v36.0 - 可视化管理器等全新升级