我们来详细讲解一下 Hive 中与 Map(映射)数据结构相关的三个非常重要的函数:map、map_keys 和 map_values。
这三个函数通常协同工作,用于创建和操作键值对(Key-Value)形式的数据。
1. map 函数
map 函数用于构造一个 Map 对象。它接收一个键值对列表(通常是交替的键和值),并将其转换为一个 Map 类型的数据。
- 语法:
map(key1, value1, key2, value2, ...) - 功能: 根据输入的参数列表创建 Map。参数必须是成对出现的,奇数位为键(Key),偶数位为值(Value)。键和值的数据类型可以不同,但所有键必须是相同类型,所有值也必须是相同类型。
- 返回值类型:
map<key_type, value_type>
示例:
假设我们有一些离散的数据,比如商品和其价格,我们想把它们组合成一个 Map。
SELECT map('apple', 5, 'banana', 3, 'orange', 8) AS price_map;
输出结果:
{"apple":5,"banana":3,"orange":8}
更实际的例子:
在真实场景中,你可能会从其他列中构造 Map。
-- 假设有一个表 products,有 name 和 price 两列
SELECT
name,
map('cost', price, 'discount', discount) AS price_info -- 创建一个包含成本和折扣的Map
FROM products;
2. map_keys 函数
map_keys 函数用于提取 Map 对象中的所有键(Key),并以数组(Array)的形式返回。
- 语法:
map_keys(map_object) - 功能: 输入一个 Map,返回一个包含该 Map 中所有键的数组。
- 返回值类型:
array<key_type>
示例:
使用上面创建好的 price_map。
SELECT
map_keys(map('apple', 5, 'banana', 3, 'orange', 8)) AS fruit_names;
输出结果:
["apple","banana","orange"]
实用场景:
常用于判断某个键是否存在于 Map 中(结合 array_contains 函数),或者用于行转列(Explode)操作后分析所有的键。
-- 判断 Map 中是否包含某个特定的键,例如 ‘banana’
SELECT
array_contains(map_keys(price_map), 'banana') AS has_banana
FROM some_table;
3. map_values 函数
map_values 函数与 map_keys 相对应,它用于提取 Map 对象中的所有值(Value),并以数组的形式返回。
- 语法:
map_values(map_object) - 功能: 输入一个 Map,返回一个包含该 Map 中所有值的数组。
- 返回值类型:
array<value_type>
示例:
同样使用上面创建好的 price_map。
SELECT
map_values(map('apple', 5, 'banana', 3, 'orange', 8)) AS fruit_prices;
输出结果:
[5,3,8]
实用场景:
常用于对 Map 中的所有值进行聚合计算,例如求总和、平均值、最大值等。
-- 计算所有水果价格的平均值
SELECT
aggregate(map_values(price_map), 0, (x, y) -> x + y, s -> s / size(price_map)) AS avg_price
FROM some_table;
-- 更简单的方法(如果Hive版本支持):可以先explode再avg
SELECT avg(price)
FROM some_table
LATERAL VIEW explode(price_map) exploded_table AS fruit, price;
综合应用示例
假设我们有一张用户行为表 user_actions,其中有一列是 map<string, bigint> 类型的 action_count,它记录了用户各种行为的次数(例如:{‘like’: 15, ‘share’: 3, ‘comment’: 7})。
| user_id | action_count |
|---|---|
| 1001 | {“like”:15, “share”:3, “comment”:7} |
| 1002 | {“like”:2, “pv”:20} |
我们可以这样使用这三个函数:
-
查看所有用户都产生了哪些类型的行为(即所有可能的键)?
这需要先收集所有键,可能会用到collect_set和explode。SELECT DISTINCT action_type FROM ( SELECT explode(map_keys(action_count)) AS action_type FROM user_actions ) t;可能的结果:
like,share,comment,pv -
计算每个用户总的行为次数(即所有值的总和)?
SELECT user_id, aggregate(map_values(action_count), 0, (acc, x) -> acc + x) AS total_actions FROM user_actions;结果:
user_id total_actions 1001 25 1002 22 -
查询哪些用户有过 ‘share’ 行为?
SELECT user_id FROM user_actions WHERE array_contains(map_keys(action_count), 'share');结果:
1001
总结
| 函数 | 作用 | 输入 | 输出 |
|---|---|---|---|
| map | 创建一个 Map 结构 | 交替的键值对列表 | map<K, V> |
| map_keys | 提取 Map 中所有的键 | 一个 Map 对象 | array<K> |
| map_values | 提取 Map 中所有的值 | 一个 Map 对象 | array<V> |
这三个函数是 Hive 中处理 Map 类型数据的基础和核心,熟练掌握它们对于进行复杂的数据提取和转换至关重要。它们通常与 explode、lateral view、array_contains 以及聚合函数结合使用,以发挥最大的威力。

2370

被折叠的 条评论
为什么被折叠?



