我有一个包含 JSON 列的表。 JSON 列内的数据组织如下:
[{"name":"Apple","short_name":"A"},{"name":"Banana","short_name":"B"}]
大多数行只有一个名称/短名称,但有些行(如上面的示例)有多个名称/短名称。我需要做的是从我的选择中删除 JSON 单元格中包含 Kiwi 的所有行。
我尝试使用
WHERE JSON_CONTAINS(persons.fruits, '"Kiwi"', '$')
,也尝试过JSON_ARRAY_CONTAINS(JSON_EXTRACT_ARRAY(persons.fruits, '$'), 'Kiwi')
并得到两个函数均未找到该函数的错误。我可能误用了这些功能,这是我第一次尝试使用它们。我该怎么办?
您必须取消数组的嵌套并在 JSON 中搜索值。有多种方法,但它们都涉及查询每行数组中可用的不同值。
以您提供的结构为例,下面的查询将过滤掉其中一个数组记录中名称为“Kiwi”的行:
WITH base_data AS (
SELECT PARSE_JSON('[{"name":"Apple","short_name":"A"},{"name":"Banana","short_name":"B"}]') as fruits_array
UNION ALL
SELECT PARSE_JSON('[{"name":"Kiwi","short_name":"K"},{"name":"Banana","short_name":"B"}]') as fruits_array
UNION ALL
SELECT PARSE_JSON('[{"name":"Apple","short_name":"A"},{"name":"Kiwi","short_name":"K"}]') as fruits_array
)
select *
from base_data
where 'Kiwi' not in (SELECT JSON_VALUE(fruit_json.name) FROM UNNEST(JSON_QUERY_ARRAY(fruits_array)) fruit_json)
假设您的值严格为 JSON,则此查询将起作用。
其工作原理:
另一种可能的解决方案是将 JSON 视为纯字符串并查找“Kiwi”的实际字符串 - 但这种方法并不完全安全,我不建议严重依赖它:
WITH base_data AS (
SELECT PARSE_JSON('[{"name":"Apple","short_name":"A"},{"name":"Banana","short_name":"B"}]') as fruits_array
UNION ALL
SELECT PARSE_JSON('[{"name":"Kiwi","short_name":"K"},{"name":"Banana","short_name":"B"}]') as fruits_array
UNION ALL
SELECT PARSE_JSON('[{"name":"Apple","short_name":"A"},{"name":"Kiwi","short_name":"K"}]') as fruits_array
)
select *
from base_data
where TO_JSON_STRING(fruits_array) NOT LIKE '%Kiwi%'