Hive 复杂数据类型实战:从 Array 到 Struct,一篇搞懂集合类数据处理

在数据仓库领域,Hive 作为基于 Hadoop 的分布式数据存储与计算工具,经常需要处理多样化的业务数据。除了基础的stringint等简单类型外,Hive 还提供了Array(数组)、Map(键值对)、Struct(结构体)三种复杂数据类型,专门用于应对嵌套、多维的业务场景(如用户标签、商品属性、考试成绩等)。

本文将结合实际业务需求,通过完整的建表、数据加载、SQL 查询案例,带大家掌握这三种复杂数据类型的核心用法,并揭秘explodestr_to_map等关键函数的实战技巧。

一、Array(数组):有序的同类型集合

1.1 基本概念与特点

Array是 Hive 中最常用的复杂类型,用于存储同一类型、有序的多个元素。其核心特点如下:

下标从 0 开始(如array[0]表示第一个元素)

访问越界不会报错,返回null(安全容错设计)

元素类型必须一致(如array<int>array<string>

1.2 实战:用 Array 存储学生多科成绩

假设我们需要存储学生的多科考试科目(如语文、数学、英语),就可以用Array类型。

1.2.1 建表与数据加载
-- 创建包含Array类型的表
create table if not exists student_subjects (
    name string,          -- 学生姓名
    subjects array<string> -- 报考科目(数组类型)
)
row format delimited 
fields terminated by '\t'         -- 字段分隔符(表级)
collection items terminated by ','; -- 数组元素分隔符(集合级)

-- 准备测试数据(/home/hivedata/array_data.txt)
-- zhangsan	chinese,math,english
-- lisi	    math,physics
-- wangwu	chinese

-- 加载数据
load data local inpath '/home/hivedata/array_data.txt' into table student_subjects;
1.2.2 关键操作:访问数组元素

Hive 中通过数组名[下标]直接访问元素:

-- 查询每个学生的第一科和第三科(注意越界返回null)
select 
    name,
    subjects[0] as first_subject,  -- 下标0(第一个元素)
    subjects[2] as third_subject    -- 下标2(第三个元素,无则返回null)
from student_subjects;

执行结果:

name    first_subject    third_subject
zhangsan chinese         english
lisi    math             null
wangwu  chinese          null

1.3 展开数组:explode 函数与 lateral view

业务中经常需要将数组 “炸开” 为多行数据(如统计所有学生的报考科目分布),这时需要用到explode函数。
explode不能直接与原表字段关联,必须配合lateral view(虚拟表关联)使用。

1.3.1 语法与逻辑
select 原表字段, 展开字段 
from 原表 
lateral view explode(数组字段) 虚拟表名 as 展开列名;
1.3.2 实战案例:统计所有报考科目
-- 将每个学生的报考科目展开为独立行
select 
    name,
    subject 
from student_subjects 
lateral view explode(subjects) sub_view as subject;

执行结果:

name    subject
zhangsan chinese
zhangsan math
zhangsan english
lisi    math
lisi    physics
wangwu  chinese

通过这一步,我们可以轻松统计 “最热门报考科目”:

-- 统计各科目被报考次数
select 
    subject,
    count(*) as cnt
from student_subjects 
lateral view explode(subjects) sub_view as subject
group by subject
order by cnt desc;

结果

subject    cnt
chinese    2
math       2
english    1
physics    1

二、Map(键值对):灵活的 KV 映射

2.1 基本概念与适用场景

Map用于存储键值对(Key-Value)集合,适合需要 “属性 - 值” 映射的场景(如商品的 “颜色 - 数量”、学生的 “学科 - 成绩”)。其特点:

键(Key)唯一,值(Value)可重复

键值对无序(与 Array 的有序性区分)

支持map<key_type, value_type>定义(如map<string, int>

2.2 实战:用 Map 存储学生各科成绩

假设需要存储学生的 “学科 - 成绩” 对应关系(如 “数学:90,语文:85”),Map是更合适的选择。

2.2.1 建表与数据加载
-- 创建包含Map类型的表
create table if not exists student_scores (
    name string,                -- 学生姓名
    score map<string, int>       -- 学科-成绩(Map类型)
)
row format delimited 
fields terminated by '\t'         -- 字段分隔符
collection items terminated by ',' -- Map元素分隔符(键值对间)
map keys terminated by ':';       -- 键值对内部分隔符(Key与Value间)

-- 准备测试数据(/home/hivedata/map_data.txt)
-- zhangsan	chinese:90,math:87,english:63
-- lisi	    chinese:60,math:30,physics:78
-- wangwu	math:25,english:81

-- 加载数据
load data local inpath '/home/hivedata/map_data.txt' into table student_scores;
2.2.2 关键操作:访问 Map 值

Hive 中通过map[key]获取对应值:

-- 查询每个学生的数学成绩(不存在则返回null)
select 
    name,
    score['math'] as math_score
from student_scores;

执行结果:

name    math_score
zhangsan 87
lisi     30
wangwu   25

2.3 字符串转 Map:str_to_map 函数

实际业务中,原始数据可能以字符串形式存储键值对(如"chinese:90,math:87"),此时需要用str_to_map函数将其转为 Map 类型。

2.3.1 函数语法
str_to_map(字符串, 键值对分隔符, 键值分隔符)
2.3.2 实战案例:将字符串转为 Map

假设原始数据存储为:

zhangsan	chinese:90|math:87|english:63  -- 键值对用|分隔,键值用:分隔
lisi	    chinese:60|math:30|physics:78

我们可以通过str_to_map动态转换:

-- 临时查询:将字符串列转为Map
select 
    name,
    str_to_map(scores_str, '\\|', ':') as score_map  -- 注意转义符\|表示|
from (
    select 
        'zhangsan' as name, 
        'chinese:90|math:87|english:63' as scores_str
    union all
    select 'lisi', 'chinese:60|math:30|physics:78'
) t;

执行后score_map字段将变为标准的 Map 类型,可以直接用score_map['math']访问值。

三、Struct(结构体):强类型的复合对象

3.1 基本概念与适用场景

Struct用于定义结构化的复合对象(类似 Java 的Class或 Python 的dict),适合需要固定格式的多属性组合场景(如学生的 “各科成绩” 需要明确字段名)。其特点:

字段名固定且有序(类似表的列)

字段类型可不同(如struct<name:string, age:int>

字段通过结构体名.字段名访问

3.2 实战:用 Struct 存储学生详细成绩

假设需要存储学生的 “语文、数学、英语、自然” 四科成绩,且要求明确每个科目的字段名,Struct是最佳选择。

3.2.1 建表与数据加载
-- 创建包含Struct类型的表
create table if not exists student_struct (
    name string,
    -- 结构体定义(各科成绩,明确字段名和类型)
    score struct<chinese:int,math:int,english:int,natrue:int>
)
row format delimited 
fields terminated by '\t'         -- 表级字段分隔符
collection items terminated by ','; -- 结构体内字段分隔符

-- 准备测试数据(/home/hivedata/struct_data.txt)
-- zhangsan	90,87,63,76
-- lisi	    60,30,78,0
-- wangwu	89,25,81,9

-- 加载数据
load data local inpath '/home/hivedata/struct_data.txt' into table student_struct;
3.2.2 关键操作:访问结构体字段

Hive 中通过结构体名.字段名访问具体值:

-- 查询数学成绩>35分的学生的英语和语文成绩
select 
    name,
    score.english as english_score,
    score.chinese as chinese_score
from student_struct 
where score.math > 35;  -- 直接通过结构体.字段过滤

执行结果:

name    english_score    chinese_score
zhangsan 63              90
wangwu   81              89

3.3 Struct vs Map:如何选择?

很多新手会混淆StructMap的使用场景,这里总结关键区别:

特征StructMap
字段名是否固定是(强类型,必须定义字段名)否(键动态,可灵活扩展)
访问方式结构体。字段名(如score.mathmap [键](如score['math']
适用场景固定格式的多属性对象(如学生成绩)动态键值对(如商品属性标签)

此时若需查询数学成绩,必须用split函数分割字符串:

select 
    name,
    split(scores, ',')[1] as math_score  -- 下标1对应数学成绩
from scores_str;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值