查询map字段
Hive Map 字段:键值对怎么存、怎么查、什么场景该用
Hive 支持 MAP 类型,用来存键值对——比如”科目:分数”、”属性:值”这种结构不确定的数据。
Map 类型适合的场景:
- 字段的 key 不固定(不同行可能有不同的键)
- 键值对的数量不固定(有的行 3 个键,有的行 10 个键)
Map 类型不适合的场景:
- 键是固定的(比如所有学生都考语数英)→ 拆成普通列
math_score、english_score,查询效率高得多 - 需要频繁按 key 过滤 → Map 字段没有索引,每次都要扫全表
原则:能用普通列就用普通列,只有键不固定的时候才用 Map。
建表:指定三层分隔符
建 Map 类型表要指定三层分隔符:
CREATE TABLE student_score (
name STRING,
score MAP<STRING, INT> -- 键:科目名,值:分数
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t' -- 列分隔符(name 和 score 之间)
COLLECTION ITEMS TERMINATED BY ',' -- Map 中键值对之间的分隔符
MAP KEYS TERMINATED BY ':'; -- 键和值之间的分隔符
数据文件格式示例:
张三 数学:90,英语:85,语文:95
李四 数学:88,英语:92
王五 语文:80,物理:75,数学:90
基本查询:取某个 key 的值
-- 查张三的数学成绩
SELECT name, score['数学'] AS math_score
FROM student_score
WHERE name = '张三';
-- 输出:张三 90
-- 查所有学生的英语成绩(没有英语成绩的返回 NULL)
SELECT name, score['英语'] AS english_score
FROM student_score;
-- 输出:
-- 张三 85
-- 李四 92
-- 王五 NULL
判断某个 key 是否存在
-- 查找有"物理"成绩的学生
SELECT name, score
FROM student_score
WHERE array_contains(map_keys(score), '物理');
-- 输出:王五 {"语文":80,"物理":75,"数学":90}
map_keys(score) 返回所有键的数组,array_contains 判断目标键是否在数组里。
获取键或值的集合
-- 查每个学生考了哪些科目
SELECT name, map_keys(score) AS subjects
FROM student_score;
-- 张三 ["数学","英语","语文"]
-- 李四 ["数学","英语"]
-- 王五 ["语文","物理","数学"]
-- 查每个学生的所有分数
SELECT name, map_values(score) AS scores
FROM student_score;
-- 张三 [90,85,95]
-- 李四 [88,92]
-- 王五 [80,75,90]
展开 Map 做聚合分析
Map 字段存的是”成组”的数据,但分析的时候经常需要”拆开”看——比如统计各科目的平均分。
用 explode(score) 把 Map 拆成多行:
-- 每个学生各科成绩展开
SELECT name, subject, s_score
FROM student_score
LATERAL VIEW explode(score) t AS subject, s_score;
-- 输出:
-- 张三 数学 90
-- 张三 英语 85
-- 张三 语文 95
-- 李四 数学 88
-- 李四 英语 92
-- 王五 语文 80
-- 王五 物理 75
-- 王五 数学 90
展开之后就可以做普通聚合了:
统计各科目平均分:
SELECT subject, AVG(s_score) AS avg_score
FROM student_score
LATERAL VIEW explode(score) t AS subject, s_score
GROUP BY subject;
-- 数学 89.33
-- 英语 88.5
-- 语文 87.5
-- 物理 75
统计每个学生平均分:
SELECT name, AVG(s_score) AS avg_score
FROM student_score
LATERAL VIEW explode(map_values(score)) t AS s_score
GROUP BY name;
-- 张三 90.0
-- 李四 90.0
-- 王五 81.67
Map 的局限性
Map 类型灵活,但有三个硬伤:
| 问题 | 说明 |
|---|---|
| 没有索引 | 查询 score['数学'] 要扫全表,不像普通列能走分区或索引 |
| key 值不统一 | 同一个 key 可能写成”数学”、”Math”、”数”,数据质量难保证 |
| 查询语法复杂 | 想按科目过滤必须 array_contains(map_keys(score), '数学'),又长又慢 |