【问题标题】:Combine two json array as key-value in mysql and create one json object在mysql中组合两个json数组作为key-value,创建一个json对象
【发布时间】:2021-04-14 22:39:55
【问题描述】:

我在 MySQL 中有两个 JSON 数组字段,如下所示:

["a", "b", "c"]
["apple", "banana", "coconut"]

现在我想将它们组合成一个 JSON 对象,如下所示:

{"a":"apple", "b":"banana", "c":"coconut"}

是否有任何 MySQL 功能?

【问题讨论】:

  • MariaDB 或 MySQL,哪个是你的?
  • 我的服务器是 MySQL 8。
  • 那么,使用JSON_TABLE() 更简单更好。

标签: mysql sql json mysql-8.0


【解决方案1】:

使用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

【讨论】:

  • 当我不知道 JSON 数组大小时,此代码不执行。
【解决方案2】:

您可以通过 JSON_EXTRACT() 函数提取数组中每个元素的索引以及通过使用来自 information_schema 的表的行生成的贡献,然后使用从返回的 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列的值

在只包含插入一行的表 (tab) 中。

Demo

【讨论】:

    【解决方案3】:

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

    • 使用 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 是一个 dbfiddle。

    请注意,这是非常通用的(您可以向行添加更多元素)。如果您在不同的行上有键/值对,并且它不使用不推荐使用的功能,您可以轻松地对其进行调整以返回多行数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-12
      • 1970-01-01
      • 2021-12-24
      • 1970-01-01
      • 2021-09-22
      相关资源
      最近更新 更多