将两个 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;

SQL sandbox

由于数组中每个元素的索引以及通过使用 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) 中只包含插入的一行。

Demo

我会用一种简单的方式来解决这个问题。

  • 使用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 多行数据。