如何选择来自 WHERE 条件的 JSON 对象的字段

问题描述

我有这张桌子

id  name   json
1   alex   {"type": "user","items": [ {"name": "banana","color": "yellow"},{"name": "apple","color": "red"} ] }
2   peter  {"type": "user","items": [ {"name": "watermelon","color": "green"},{"name": "pepper","color": "red"} ] }
3   john   {"type": "user","items": [ {"name": "tomato","color": "red"} ] }
4   carl   {"type": "user","items": [ {"name": "orange","color": "orange"},{"name": "nut","color": "brown"} ] }

重要的是,每个 json 对象可以有不同数量的“项目”,但我需要的是在 WHERE 条件下匹配的对象的“产品名称”。

我想要的输出是前两列和项目的名称,其中颜色类似于 %red%:

id name  fruit
1  alex  apple
2  peter pepper
3  john  tomato
select id,name,***** (this is what I don't kNow) FROM table
where JSON_EXTRACT(json,"$.items[*].color") like  '%red%'

解决方法

如果您运行的是 MySQL 8.0,我会推荐 json_table()

select t.id,t.name,x.name as fruit
from mytable t
cross join json_table(
    t.js,'$.items[*]' columns (name varchar(50) path '$.name',color varchar(50) path '$.color')
) x
where x.color = 'red'

MariaDB 中未实现此功能。我们可以借助数字表手动取消嵌套:

select t.id,json_unquote(json_extract(t.js,concat('$.items[',x.num,'].name'))) as fruit
from mytable t
inner join (select 0 as num union all select 1 union all select 2 ...) x(num)
    on x.num < json_length(t.js,'$.items')
where json_unquote(json_extract(t.js,'].color'))) = 'red'
,

您可以将 JSON_EXTRACT() 函数与 Recursive Common Table Expression 一起使用以动态生成行,例如

WITH RECURSIVE cte AS 
(
  SELECT 1 AS n
  UNION ALL
  SELECT n + 1
    FROM cte
   WHERE cte.n < (SELECT MAX(JSON_LENGTH(json)) FROM t )
)
SELECT id,name,JSON_UNQUOTE(JSON_EXTRACT(json,CONCAT('$.items[',n-1,'].name'))) AS fruit
  FROM cte
  JOIN t
 WHERE JSON_EXTRACT(json,'].color')) = "red"

Demo

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...