You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Presto中筛选数组内存在指定JSON字段的行并避免报错

问题描述

我有一个字段jsonCol,存储的是JSON对象数组,示例数据如下:
第一行数据:

[{'name': 'fieldA', 'enum': 'someValA'},
 {'name': 'fieldB', 'enum': 'someValB'},
 {'name': 'fieldC', 'enum': 'someValC'}]

第二行数据:

[{'name': 'fieldA', 'enum': 'someValA'},
 {'name': 'fieldC', 'enum': 'someValC'}]

我需要筛选出包含fieldB且其enum值为someValB的行,但当前查询在fieldB不存在时会报错:

Error running query: Array subscript must be less than or equal to array length: 1 > 0

当前使用的查询语句:

SELECT
    json_extract_scalar(filter(cast(json_parse(jsonCol) AS array(json)), x -> json_extract_scalar(x, '$.name') = 'fieldB')[1], '$.enum') AS myField
FROM myTable
WHERE
    json_extract_scalar(filter(cast(json_parse(jsonCol) AS array(json)), x -> json_extract_scalar(x, '$.name') = 'fieldB')[1], '$.enum') = 'someValB'

请问如何实现既检查someValB的值,又能忽略fieldB不存在的情况?

解决方案

报错根源是:当fieldB不存在时,filter返回空数组,直接用[1]访问下标会触发数组越界(数组下标从0开始,空数组长度为0,无法访问下标1)。以下三种方法可以解决这个问题:

方法1:先判断数组长度再处理

先提取匹配fieldB的数组,用cardinality()函数判断数组长度,过滤掉空数组的行后再取值,避免越界:

SELECT
    json_extract_scalar(filtered_b[1], '$.enum') AS myField
FROM myTable
CROSS JOIN UNNEST([cast(json_parse(jsonCol) AS array(json))]) AS t(arr)
CROSS JOIN UNNEST([filter(arr, x -> json_extract_scalar(x, '$.name') = 'fieldB')]) AS t(filtered_b)
WHERE
    cardinality(filtered_b) > 0
    AND json_extract_scalar(filtered_b[1], '$.enum') = 'someValB'

这种方式把重复的filter计算提取出来,既避免了下标越界,也提升了查询效率。

方法2:用try()函数捕获错误

如果你的SQL环境支持try()函数,可以用它包裹下标访问逻辑,出错时返回NULL,再通过WHERE条件排除这些行:

SELECT
    try(json_extract_scalar(filter(cast(json_parse(jsonCol) AS array(json)), x -> json_extract_scalar(x, '$.name') = 'fieldB')[1], '$.enum')) AS myField
FROM myTable
WHERE
    try(json_extract_scalar(filter(cast(json_parse(jsonCol) AS array(json)), x -> json_extract_scalar(x, '$.name') = 'fieldB')[1], '$.enum')) = 'someValB'

try()会自动捕获下标越界错误并返回NULL,WHERE条件会直接排除这些NULL行。

方法3:用exists判断元素存在性

最简洁的方式是通过UNNEST展开数组,用exists子查询判断是否存在符合条件的元素,彻底避开数组下标操作:

SELECT
    json_extract_scalar(filter(cast(json_parse(jsonCol) AS array(json)), x -> json_extract_scalar(x, '$.name') = 'fieldB')[1], '$.enum') AS myField
FROM myTable
WHERE
    exists (
        SELECT 1
        FROM UNNEST(cast(json_parse(jsonCol) AS array(json))) AS x
        WHERE json_extract_scalar(x, '$.name') = 'fieldB'
          AND json_extract_scalar(x, '$.enum') = 'someValB'
    )

这种方式逻辑更直观,直接检查数组中是否存在满足条件的元素,从根源上避免了下标越界问题。

内容的提问来源于stack exchange,提问作者skbrhmn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 08:34:56