将两个 json 数组组合为 mysql 中的键值并创建一个 json 对象
Combine two json array as key-value in mysql and create one json object
我在 MySQL 中有两个 JSON 数组字段,如下所示:
["a", "b", "c"]
["apple", "banana", "coconut"]
现在我想像这样将它们组合成一个 JSON 对象:
{"a":"apple", "b":"banana", "c":"coconut"}
有什么MySQL函数吗?
使用 JSON functions 的基本方法如下:
select JSON_OBJECT(
JSON_UNQUOTE(JSON_EXTRACT(a, '$[0]')), JSON_EXTRACT(b, '$[0]'),
JSON_UNQUOTE(JSON_EXTRACT(a, '$[1]')), JSON_EXTRACT(b, '$[1]'),
JSON_UNQUOTE(JSON_EXTRACT(a, '$[2]')), JSON_EXTRACT(b, '$[2]')
) result from tbl;
由于数组中每个元素的索引以及通过使用 information_schema
中的 table 行生成的贡献,您可以通过 JSON_EXTRACT()
函数提取,然后聚合使用 JSON_OBJECTAGG()
从子查询返回的所有结果,例如
SELECT JSON_OBJECTAGG(Js1,Js2)
FROM
(
SELECT JSON_UNQUOTE(JSON_EXTRACT(jsdata1,CONCAT('$[',@rn+1,']'))) AS Js1,
JSON_UNQUOTE(JSON_EXTRACT(jsdata2,CONCAT('$[',@rn+1,']'))) AS Js2,
@rn := @rn + 1 AS rn
FROM tab AS t1
JOIN (SELECT @rn:=-1) AS r
JOIN information_schema.tables AS t2
-- WHERE @rn < JSON_LENGTH(jsdata1) - 1 #redundant for MariaDB, but needed for MySQL
) AS j
哪里
'["a", "b", "c"]'
假定为列 jsdata1
和
的值
'["apple", "banana", "coconut"]'
假定为 jsdata2
列的值
在 table(tab
) 中只包含插入的一行。
我会用一种简单的方式来解决这个问题。
- 使用
JSON_TABLE()
取消两个JSON结构的嵌套。
- 将两个表连接在一起。
- 构造适当的 JSON 对象并聚合。
下面实现了这个逻辑。第一个 CTE 提取密钥。第二个提取值,最后合并这些值:
WITH the_keys as (
SELECT j.*
FROM t CROSS JOIN
JSON_TABLE(t.jsdata1,
'$[*]'
columns (seqnum for ordinality, the_key varchar(255) path '$')
) j
),
the_values as (
SELECT j.*
FROM t CROSS JOIN
JSON_TABLE(t.jsdata2,
'$[*]'
columns (seqnum for ordinality, val varchar(255) path '$')
) j
)
select json_objectagg(the_keys.the_key, the_values.val)
from the_keys join
the_values
on the_keys.seqnum = the_values.seqnum;
Here 是一个 db<>fiddle.
请注意,这是非常普遍的(您可以向行添加更多元素)。如果您在不同的行上有 key/value 对,并且它不使用不推荐使用的功能,您可以轻松地将其调整为 return 多行数据。
我在 MySQL 中有两个 JSON 数组字段,如下所示:
["a", "b", "c"]
["apple", "banana", "coconut"]
现在我想像这样将它们组合成一个 JSON 对象:
{"a":"apple", "b":"banana", "c":"coconut"}
有什么MySQL函数吗?
使用 JSON functions 的基本方法如下:
select JSON_OBJECT(
JSON_UNQUOTE(JSON_EXTRACT(a, '$[0]')), JSON_EXTRACT(b, '$[0]'),
JSON_UNQUOTE(JSON_EXTRACT(a, '$[1]')), JSON_EXTRACT(b, '$[1]'),
JSON_UNQUOTE(JSON_EXTRACT(a, '$[2]')), JSON_EXTRACT(b, '$[2]')
) result from tbl;
由于数组中每个元素的索引以及通过使用 information_schema
中的 table 行生成的贡献,您可以通过 JSON_EXTRACT()
函数提取,然后聚合使用 JSON_OBJECTAGG()
从子查询返回的所有结果,例如
SELECT JSON_OBJECTAGG(Js1,Js2)
FROM
(
SELECT JSON_UNQUOTE(JSON_EXTRACT(jsdata1,CONCAT('$[',@rn+1,']'))) AS Js1,
JSON_UNQUOTE(JSON_EXTRACT(jsdata2,CONCAT('$[',@rn+1,']'))) AS Js2,
@rn := @rn + 1 AS rn
FROM tab AS t1
JOIN (SELECT @rn:=-1) AS r
JOIN information_schema.tables AS t2
-- WHERE @rn < JSON_LENGTH(jsdata1) - 1 #redundant for MariaDB, but needed for MySQL
) AS j
哪里
'["a", "b", "c"]'
假定为列 jsdata1
和
'["apple", "banana", "coconut"]'
假定为 jsdata2
在 table(tab
) 中只包含插入的一行。
我会用一种简单的方式来解决这个问题。
- 使用
JSON_TABLE()
取消两个JSON结构的嵌套。 - 将两个表连接在一起。
- 构造适当的 JSON 对象并聚合。
下面实现了这个逻辑。第一个 CTE 提取密钥。第二个提取值,最后合并这些值:
WITH the_keys as (
SELECT j.*
FROM t CROSS JOIN
JSON_TABLE(t.jsdata1,
'$[*]'
columns (seqnum for ordinality, the_key varchar(255) path '$')
) j
),
the_values as (
SELECT j.*
FROM t CROSS JOIN
JSON_TABLE(t.jsdata2,
'$[*]'
columns (seqnum for ordinality, val varchar(255) path '$')
) j
)
select json_objectagg(the_keys.the_key, the_values.val)
from the_keys join
the_values
on the_keys.seqnum = the_values.seqnum;
Here 是一个 db<>fiddle.
请注意,这是非常普遍的(您可以向行添加更多元素)。如果您在不同的行上有 key/value 对,并且它不使用不推荐使用的功能,您可以轻松地将其调整为 return 多行数据。