MAP
MAPMAP
是键值对数据类型,用于存储动态属性、名称到值的映射。与
STRUCTSTRUCT
(固定字段名)不同,MAP 的键在运行时确定,适合字段数量不固定的场景。
与复杂类型的选型参考:
类型 结构 适合场景 MAP<K,V>MAP<K,V>
键值对,键类型统一 动态属性、配置项、名称到值的映射 STRUCT<f:T,...>STRUCT<f:T,...>
命名字段,类型各异 固定结构的对象,字段名在建表时确定 ARRAY<T>ARRAY<T>
有序列表,元素类型统一 标签、评分、ID 列表
语法与定义
类型声明
MAP<keyType, valueType>
keyTypekeyType
:键类型,支持基本类型(STRINGSTRING
、INTINT
、BIGINTBIGINT
、DOUBLEDOUBLE
等),不支持 ARRAYARRAY
、MAPMAP
、STRUCTSTRUCT
valueTypevalueType
:值类型,支持基本类型和复杂类型
构造方式
-- MAP() 构造函数:键值交替排列,参数数量必须为偶数
MAP(key1, value1, key2, value2, ...)
-- map_from_arrays():从两个数组分别提供键和值
map_from_arrays(keys_array, values_array)
元素访问 :键不存在时返回
NULLNULL
,不报错:
MAP('a', 1, 'b', 2)['a'] -- 1
MAP('a', 1, 'b', 2)['z'] -- NULL
建表与写入
CREATE TABLE doc_map_demo (
id INT,
attrs MAP<STRING, INT>,
meta MAP<STRING, STRING>
);
INSERT INTO doc_map_demo VALUES
(1, MAP('age', 25, 'score', 90), MAP('dept', 'Eng', 'level', 'senior')),
(2, MAP('age', 30, 'score', 85), MAP('dept', 'HR', 'level', 'junior')),
(3, MAP('age', 28), MAP('dept', 'Eng'));
查询基本信息:
SELECT id,
attrs['age'] AS age,
attrs['score'] AS score,
size(attrs) AS attr_count
FROM doc_map_demo
ORDER BY id;
id age score attr_count 1 25 90 2 2 30 85 2 3 28 NULL 1
常用函数
函数 说明 size(m)size(m)
/ cardinality(m)cardinality(m)
键值对数量 map_keys(m)map_keys(m)
返回所有键组成的 ARRAY map_values(m)map_values(m)
返回所有值组成的 ARRAY element_at(m, key)element_at(m, key)
按键取值,等价于 m[key]m[key]
map_from_arrays(keys, values)map_from_arrays(keys, values)
从两个数组构造 MAP map_concat(m1, m2, ...)map_concat(m1, m2, ...)
合并多个 MAP,重复键取后者 的值 map_filter(m, (k,v) -> cond)map_filter(m, (k,v) -> cond)
保留满足条件的键值对 transform_values(m, (k,v) -> expr)transform_values(m, (k,v) -> expr)
对每个值应用函数,键不变 transform_keys(m, (k,v) -> expr)transform_keys(m, (k,v) -> expr)
对每个键应用函数,值不变
map_from_arrays 示例
SELECT map_from_arrays(['a', 'b', 'c'], [1, 2, 3]) AS m;
-- 返回:{"a":1,"b":2,"c":3}
map_concat 示例
重复键取后者的值:
SELECT map_concat(MAP('a', 1, 'b', 2), MAP('b', 99, 'c', 3)) AS merged;
-- 返回:{"a":1,"b":99,"c":3}
高阶函数示例
-- 保留值大于 1 的键值对
SELECT map_filter(MAP('a', 1, 'b', 2, 'c', 3), (k, v) -> v > 1) AS filtered;
-- 返回:{"b":2,"c":3}
-- 所有值乘以 10
SELECT transform_values(MAP('a', 1, 'b', 2), (k, v) -> v * 10) AS scaled;
-- 返回:{"a":10,"b":20}
-- 键转大写
SELECT transform_keys(MAP('a', 1, 'b', 2), (k, v) -> UPPER(k)) AS upper_keys;
-- 返回:{"A":1,"B":2}
聚合与展开
MAP_AGG — 行转 MAP
将多行的键值聚合为一个 MAP:
SELECT MAP_AGG(name, score) AS score_map
FROM (
SELECT 'Alice' AS name, 95 AS score UNION ALL
SELECT 'Bob', 87 UNION ALL
SELECT 'Carol', 92
) t;
-- 返回:{"Alice":95,"Bob":87,"Carol":92}
配合
GROUP BYGROUP BY
按分组聚合:
SELECT dept, MAP_AGG(name, score) AS scores
FROM (
SELECT 'Alice' AS name, 95 AS score, 'Eng' AS dept UNION ALL
SELECT 'Bob', 87, 'Eng' UNION ALL
SELECT 'Carol', 92, 'HR'
) t
GROUP BY dept
ORDER BY dept;
dept scores Eng {"Alice":95,"Bob":87} HR {"Carol":92}
EXPLODE — MAP 展开为行
EXPLODEEXPLODE
将 MAP 展开为多行,每行一个键值对:
SELECT id, k, v
FROM doc_map_demo
LATERAL VIEW EXPLODE(attrs) tmp AS k, v
ORDER BY id, k;
id k v 1 age 25 1 score 90 2 age 30 2 score 85 3 age 28
类型转换
-- 转换值类型
SELECT CAST(MAP('a', 1, 'b', 2) AS MAP<STRING, BIGINT>) AS cast_map;
-- 返回:{"a":1,"b":2}(值类型变为 bigint)
CAST to STRING 与 TO_JSON 的格式区别 :
SELECT CAST(MAP('a', 1, 'b', 2) AS STRING); -- {a -> 1, b -> 2}(非 JSON 格式)
SELECT TO_JSON(MAP('a', 1, 'b', 2)); -- {"a":1,"b":2}(标准 JSON)
⚠️ MAP 的 CAST to STRING 输出格式为
{key -> value, ...}{key -> value, ...}
,不是 JSON。如需 JSON 格式,使用
TO_JSONTO_JSON
。
NULL 处理
-- NULL 值合法
SELECT MAP('a', NULL, 'b', 2) AS null_val;
-- 返回:{"a":null,"b":2}
-- 访问值为 NULL 的键,返回 NULL(与键不存在无法区分)
SELECT MAP('a', NULL, 'b', 2)['a']; -- NULL
SELECT MAP('a', NULL, 'b', 2)['z']; -- NULL
⚠️ MAP 的键不能为 NULL,运行时会报错:
the key of map cannot be nullthe key of map cannot be null
。
注意事项
MAP 不支持 ==
比较运算符,不能用作 ORDER BYORDER BY
、GROUP BYGROUP BY
或 JOIN 键。
同一 MAP 中所有键类型必须一致,所有值类型也必须一致。
MAP()MAP()
和 map_from_arrays()map_from_arrays()
均不会自动去重重复键。重复键的行为:map_keysmap_keys
保留所有重复键,m[key]m[key]
返回第一个匹配值,TO_JSONTO_JSON
保留所有重复键(如 {"k":1,"k":2}{"k":1,"k":2}
)。构建 MAP 前应确保键唯一。
map_keysmap_keys
和 map_valuesmap_values
返回的数组顺序与插入顺序一致,但不保证跨版本稳定。
相关文档