STRUCT
STRUCT
STRUCT
是复合数据类型,将多个不同类型的字段组合为一个命名字段集合。适合将关联数据存储在同一列中,如将用户的姓名、年龄、状态作为一个整体存储,或在 ARRAY 中存储结构化对象。
与复杂类型的选型参考:
| 类型 | 结构 | 适合场景 |
|---|
STRUCT<f:T,...>
STRUCT<f:T,...> | 命名字段,类型各异 | 固定结构的对象,字段名在建表时确定 |
MAP<K,V>
MAP<K,V> | 键值对,键类型统一 | 动态属性,字段数量不固定 |
ARRAY<T>
ARRAY<T> | 有序列表,元素类型统一 | 标签、评分、ID 列表 |
语法与定义
类型声明
STRUCT<field1_name: field1_type, field2_name: field2_type, ...>
构造函数
-- named_struct:指定字段名(推荐)
named_struct('field1_name', value1, 'field2_name', value2, ...)
-- struct:自动生成字段名 col1、col2、...
struct(value1, value2, ...)
字段访问:字段名大小写不敏感:
named_struct('Name', 'Alice', 'age', 30).name -- Alice
named_struct('Name', 'Alice', 'age', 30).Name -- Alice(同一字段)
建表与写入
CREATE TABLE doc_struct_demo (
id INT,
person STRUCT<name: STRING, age: INT, active: BOOLEAN>
);
INSERT INTO doc_struct_demo VALUES
(1, named_struct('name', 'Alice', 'age', 30, 'active', true)),
(2, named_struct('name', 'Bob', 'age', 25, 'active', false)),
(3, named_struct('name', 'Carol', 'age', NULL, 'active', true));
查询整列与字段访问:
SELECT id, person, person.name, person.age, person.active
FROM doc_struct_demo
ORDER BY id;
| id | person | name | age | active |
|---|
| 1 | {"name":"Alice","age":30,"active":true} | Alice | 30 | true |
| 2 | {"name":"Bob","age":25,"active":false} | Bob | 25 | false |
| 3 | {"name":"Carol","age":null,"active":true} | Carol | NULL | true |
构造函数对比
-- named_struct:字段名自定义
SELECT named_struct('company', 'ClickZetta', 'headcount', 5) AS s1;
-- 返回:{"company":"ClickZetta","headcount":5}
-- struct:字段名自动生成为 col1、col2、...
SELECT struct('Alice', 30, true) AS s2;
-- 返回:{"col1":"Alice","col2":30,"col3":true}
⚠️
struct()
struct()
生成的字段名(
col1
col1
、
col2
col2
)不具可读性,建议使用
named_struct()
named_struct()
明确指定字段名。
修改字段值
STRUCT 字段不能单独修改,需使用
struct_update()
struct_update()
函数:
SELECT struct_update(
named_struct('name', 'Alice', 'age', 30, 'active', true),
'age', 31
) AS updated;
-- 返回:{"name":"Alice","age":31,"active":true}
struct_update
struct_update
只修改指定字段,其余字段保持不变。
嵌套 STRUCT
STRUCT 的字段类型可以是另一个 STRUCT,使用链式点符号访问嵌套字段:
SELECT named_struct(
'outer', named_struct('inner_val', 42, 'label', 'test'),
'count', 3
) AS nested;
-- 返回:{"outer":{"inner_val":42,"label":"test"},"count":3}
-- 访问嵌套字段
SELECT named_struct(
'outer', named_struct('inner_val', 42, 'label', 'test'),
'count', 3
).outer.inner_val AS deep_val;
-- 返回:42
STRUCT 与 ARRAY 组合
STRUCT 常与 ARRAY 组合,用于存储结构化对象列表:
-- 构造 STRUCT 数组
SELECT ARRAY(
named_struct('name', 'Alice', 'score', 95),
named_struct('name', 'Bob', 'score', 87)
) AS students;
-- 返回:[{"name":"Alice","score":95},{"name":"Bob","score":87}]
用
EXPLODE
EXPLODE
展开 STRUCT 数组,再通过字段访问提取各字段:
SELECT s.name, s.score
FROM (
SELECT ARRAY(
named_struct('name', 'Alice', 'score', 95),
named_struct('name', 'Bob', 'score', 87)
) AS students
) t
LATERAL VIEW EXPLODE(students) tmp AS s;
类型转换
-- 转换字段类型
SELECT CAST(named_struct('a', 1, 'b', 2) AS STRUCT<a:BIGINT, b:BIGINT>) AS cast_struct;
-- 返回:{"a":1,"b":2}(字段类型变为 bigint)
CAST to STRING 与 TO_JSON 的格式区别:
SELECT CAST(named_struct('name', 'Alice', 'age', 30) AS STRING);
-- 返回:{Alice, 30}(只有值,无字段名,非 JSON)
SELECT TO_JSON(named_struct('name', 'Alice', 'age', 30));
-- 返回:{"name":"Alice","age":30}(标准 JSON,含字段名)
⚠️ STRUCT 的 CAST to STRING 只输出字段值,不含字段名,格式为
{val1, val2, ...}
{val1, val2, ...}
。如需 JSON 格式,使用
TO_JSON
TO_JSON
。
NULL 处理
STRUCT 的任意字段均可为 NULL:
SELECT named_struct('name', NULL, 'age', 30) AS s;
-- 返回:{"name":null,"age":30}
按结构体字段过滤时,NULL 字段参与比较会返回 NULL(不是 true 或 false):
SELECT id, person.name
FROM doc_struct_demo
WHERE person.age > 26;
-- id=3 的 age 为 NULL,该行不出现在结果中
注意事项
- STRUCT 支持
=
=
相等比较,不支持 >
>
、<
<
等大小比较,也不支持作为 GROUP BY 键或 JOIN 键。
- 字段名在同一 STRUCT 内必须唯一。
- 字段名大小写不敏感,
person.Name
person.Name
和 person.name
person.name
访问同一字段。
- CAST to STRING 只输出值,不含字段名;如需含字段名的 JSON,使用
TO_JSON
TO_JSON
。
相关文档