构造带条件的JSON_ARRAY:排除值为3的第二个对象
动态生成不含特定值的JSON数组
示例表
| f1 | f2 |
|---|---|
| 1 | 2 |
| 1 | 3 |
需求
为每行生成JSON数组,当f2的值为3时,不包含对应的{"num": f2}对象,期望结果:
[{"num":1},{"num":2}] [{"num":1}]
问题分析
你尝试将IF嵌套在JSON_ARRAY中,但会生成空对象而非直接省略:
SELECT JSON_ARRAY( JSON_OBJECT('num', f1), IF(f2 <> 3, JSON_OBJECT('num', f2), JSON_OBJECT()) ) FROM sample_table;
得到的结果:
[{"num": 1}, {"num": 2}] [{"num": 1}, {}]
解决方案
方案1:避免生成空对象(更简洁)
利用JSON_MERGE_PRESERVE合并数组,当f2=3时传入空数组,完全避免空对象的生成:
SELECT JSON_MERGE_PRESERVE( JSON_ARRAY(JSON_OBJECT('num', f1)), IF(f2 <> 3, JSON_ARRAY(JSON_OBJECT('num', f2)), JSON_ARRAY()) ) FROM sample_table;
这种写法比外层嵌套IF更简洁,仅重复了JSON_ARRAY(),无需重复编写完整的对象生成逻辑。
方案2:过滤已生成的空对象(MySQL 8.0.17+)
若你的MySQL版本为8.0.17及以上,可直接用JSON_FILTER过滤数组中的空对象:
SELECT JSON_FILTER( JSON_ARRAY( JSON_OBJECT('num', f1), IF(f2 <> 3, JSON_OBJECT('num', f2), JSON_OBJECT()) ), '$[*] != {}' ) FROM sample_table;
$[*] != {}是JSONPath表达式,用于保留数组中所有非空对象的元素。
方案3:简化外层IF写法(可选)
如果不想用合并或过滤,也可以抽取重复逻辑减少代码冗余:
SELECT IF( f2 <> 3, JSON_ARRAY(j1, JSON_OBJECT('num', f2)), JSON_ARRAY(j1) ) FROM (SELECT f1, f2, JSON_OBJECT('num', f1) AS j1 FROM sample_table) t;
通过子查询预先生成重复的{"num": f1}对象,避免主查询中重复编写相同代码。
内容的提问来源于stack exchange,提问作者da Bich
相关产品推荐
相关产品推荐

