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. 语法详解

语法结构
sql 复制代码
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 是一个数组:

sql 复制代码
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 关键词:

sql 复制代码
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 存储的是用户标签的数组,如下所示:

id tags
1 ['admin', 'user']
2 ['user']

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

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

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

tag count
admin 1
user 2

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

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

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

id name interests
1 Alice music,books
2 Bob sports,games,books

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

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

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

sql 复制代码
SELECT id, name, SPLIT(interests, ',') as interest_array
FROM users;

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

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

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

sql 复制代码
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

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

id name interest
1 Alice music
1 Alice books
2 Bob sports
2 Bob games
2 Bob books
步骤 3: 统计每个兴趣爱好的出现次数

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

sql 复制代码
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;

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

interest count
music 1
books 2
sports 1
games 1

6. 操作层面

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

示例代码:

sql 复制代码
-- 将 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,还是来举个🌰:

      sql 复制代码
      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后生成的字段和原始字段本身就不冲突时,可以忽略掉表名,简化如下:

      sql 复制代码
      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 字段;这个地方涉及到变量作用域的问题,展开说其实有点多,有心的同学这个地方可以稍微注意一下!!!

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

相关推荐
lucky_syq3 小时前
Spark和Hive的联系
大数据·hive·spark
Azoner8 小时前
hdfs balancer 指定节点做负载均衡
hadoop·hdfs·负载均衡
goTsHgo10 小时前
Hive on Spark 离线数据仓库中拉链表全流程使用
数据仓库·hive·spark
出发行进14 小时前
Hive其九,排名函数,练习和自定义函数
大数据·数据仓库·hive·hadoop·数据分析
drebander14 小时前
SQL 实战:日期与时间函数 – 统计数据的时间跨度与趋势
linux·数据库·sql
随猿Fa15 小时前
arthas查看拼接好参数的sql, redis, es完整可直接执行的命令
redis·sql·elasticsearch
m0_7482359517 小时前
Python毕业设计选题:基于Hadoop 的国产电影数据分析与可视化_django+spider
hadoop·python·课程设计
工业互联网专业18 小时前
Python大数据可视化:基于Python对B站热门视频的数据分析与研究_flask+hive+spider
hive·python·数据分析·flask·毕业设计·源码·spider
沙滩de流沙20 小时前
Hadoop生态
大数据·hadoop·分布式