JSON_TUPLE 一次取出多个 JSON 字段
JSON_TUPLE 一次从 JSON 字符串中取出多个键,比多次调用 GET_JSON_OBJECT 更省解析开销。MaxCompute、Hive 和 Spark 支持;Hologres、StarRocks、Doris 和 Flink SQL 没有这个函数,需要按键逐个提取。
各引擎写法
| 引擎 | 支持 | 写法 | 说明 | 依据 |
|---|---|---|---|---|
| MaxCompute | 支持 | JSON_TUPLE(json, key1, key2, ...) | 返回值都是 STRING,key 支持用 ['...'] 表示带特殊字符的键,也支持多层路径。 | 官方文档 |
| Hologres | 需改写 | GET_JSON_OBJECT(json, '$.key') | 没有 JSON_TUPLE,可以按键多次调用 hive_compatible 扩展中的 GET_JSON_OBJECT。 | 官方文档 |
| StarRocks | 需改写 | get_json_string(json_str, '$.key') | 没有 JSON_TUPLE,按键多次调用 get_json_string,它的别名是 get_json_object。 | 官方文档 |
| Doris | 需改写 | GET_JSON_STRING(json_str, '$.key') | 没有 JSON_TUPLE。GET_JSON_STRING 是 JSON_EXTRACT_STRING 的别名。 | 官方文档 |
| Hive | 支持 | json_tuple(jsonStr, k1, k2, ...) | Hive 0.7 起提供,是表生成函数,通常配合 LATERAL VIEW 使用。 | 官方文档 |
| Spark SQL | 支持 | json_tuple(jsonStr, p1, p2, ..., pn) | 所有参数和输出列都是字符串。 | 官方文档 |
| Flink SQL | 需改写 | JSON_VALUE(json, '$.key') | 没有 JSON_TUPLE,按键多次调用 JSON_VALUE。 | 官方文档 |
迁移注意事项
- Hive 的 json_tuple 是表生成函数,常见写法是 LATERAL VIEW json_tuple(...) t AS a, b。迁到没有这个函数的引擎时,要把 LATERAL VIEW 拆成 SELECT 中的多个提取函数。
- json_tuple 的键是顶层字段名,取嵌套字段时 Hive 和 Spark 要再套一层。MaxCompute 支持在 key 中写多层路径,迁移到 Hive 或 Spark 时要改写。
- 改成逐个提取后,每个键都会解析一遍 JSON。键很多时性能会下降,可以考虑在 StarRocks 或 Doris 中把列改成 JSON 类型。
示例
从埋点 JSON 中取事件 ID 和事件名
SELECT JSON_TUPLE(event_json, 'event_id', 'event_name') AS (event_id, event_name) FROM events;SELECT GET_JSON_OBJECT(event_json, '$.event_id') AS event_id, GET_JSON_OBJECT(event_json, '$.event_name') AS event_name FROM events;SELECT get_json_string(event_json, '$.event_id') AS event_id, get_json_string(event_json, '$.event_name') AS event_name FROM events;SELECT GET_JSON_STRING(event_json, '$.event_id') AS event_id, GET_JSON_STRING(event_json, '$.event_name') AS event_name FROM events;SELECT t.event_id, t.event_name FROM events LATERAL VIEW json_tuple(event_json, 'event_id', 'event_name') t AS event_id, event_name;SELECT json_tuple(event_json, 'event_id', 'event_name') AS (event_id, event_name) FROM events;SELECT JSON_VALUE(event_json, '$.event_id') AS event_id, JSON_VALUE(event_json, '$.event_name') AS event_name FROM events;