【问题标题】:MariaDB/MySQL - Convert keys and values from json object into rows, using JSON_TABLEMariaDB/MySQL - 使用 JSON_TABLE 将键和值从 json 对象转换为行
【发布时间】:2023-01-29 22:36:32
【问题描述】:

使用 Mariadb 10.6 - 在以下示例中,我尝试将 json 对象的条目转换为表行:

SELECT *
FROM JSON_TABLE('{ 
   "1": [1, 123.25], 
   "10": [2, 110.5], 
   "100": [3, 105.75] 
}', '$.*' COLUMNS (
    col1 decimal(13,2) PATH '$',
    col2 int PATH '$[0]',
    col3 decimal(17,2) PATH '$[1]'
)) table1

结果是:

col1 col2 col3
NULL 1 123.25
NULL 2 110.50
NULL 3 105.75

有没有办法用属性键(“1”、“10”、“100”)填充“col1”?

我想有一些“关键词”来引用密钥,但我在 MariaDB 或 MySQL 的文档中找不到任何关于此的信息。

我已经做了一个例程,通过循环 JSON_KEYS 的输出来创建一个临时表,但如果我可以使用 JSON_TABLE 来完成这项工作,它会更优雅。

【问题讨论】:

    标签: json mariadb


    【解决方案1】:

    这是一种无需例程即可完成此操作的方法:

    • 使用JSON_TABLE 提取您的 json 值,使用FOR ORDINALITY 提取行号
    • 使用JSON_KEYS提取你的密钥
    • 对于每条记录,提取对应于第i个排名值的第i个键,由行号给出,使用JSON_EXTRACT
    SELECT JSON_EXTRACT(JSON_KEYS(@json), 
                        CONCAT('$[', table1.rowid-1, ']')) AS col1, 
           table1.col2,
           table1.col3
    FROM JSON_TABLE(@json, '$.*' COLUMNS (
        rowid FOR ORDINALITY,
        col2 int PATH '$[0]',
        col3 decimal(17,2) PATH '$[1]'
    )) table1
    

    输出:

    col1 col2 col3
    "1" 1 123.25
    "10" 2 110.50
    "100" 3 105.75

    查看演示 here

    【讨论】:

    • 这是一个很好的解决方法,但我很难相信 JSON_TABLE 中没有任何内置功能可以解决此任务。
    • 如果有人在仅使用JSON_TABLE 时发布查询,我将与您一起学习。据我尝试,由于子查询,它变得更加混乱。
    【解决方案2】:

    这是使用CROSS JOINJSON_TABLEJSON_KEYS的另一种方法:

    JSON_KEYS(json) 将给我们["1", "10", "100"]

    CROSS JOIN用于从["1", "10", "100"]生成多行

    WITH data AS
    ( 
     SELECT '{
               "1": [1, 123.25], 
               "10": [2, 110.5], 
               "100": [3, 105.75] 
             }' AS json
    )
    SELECT k.key, c.col2, c.col3
      FROM data
     CROSS JOIN JSON_TABLE(
                           JSON_KEYS(json), 
                           '$[*]' COLUMNS(
                                           rowid FOR ORDINALITY, 
                                           key TEXT PATH '$'
                                          )
                          ) k
     INNER JOIN 
       (SELECT cols.*
          FROM data,
               JSON_TABLE(
                          json,
                          '$.*' COLUMNS(
                                         rowid FOR ORDINALITY,
                                         col2 int PATH '$[0]',
                                         col3 decimal(17, 2) PATH '$[1]'
                                        )
                          ) AS cols) AS c
        ON c.rowid = k.rowid;
    

    demo here

    【讨论】:

      【解决方案3】:

      我回答我自己的问题: 很抱歉,显然没有任何本机选项可以使用 JSON_TABLE(目前)引用 json 对象中的键名,目前发布的两个解决方法都很棒。 我最终使用了两者的混合物:

      SET @json = '{ "1": [1, 123.25], "10": [2, 110.5], "100": [3, 105.75] }';
      
      SELECT
          col1,
          JSON_EXTRACT(@json, CONCAT('$."', col1, '"[0]')) col2,
          JSON_EXTRACT(@json, CONCAT('$."', col1, '"[1]')) col3
      FROM JSON_TABLE(JSON_KEYS(@json), '$[*]' COLUMNS (col1 varchar(20) PATH '$')) t1;
      

      【讨论】:

        猜你喜欢
        • 2021-03-10
        • 2018-02-20
        • 1970-01-01
        • 2016-03-18
        • 2020-08-30
        • 1970-01-01
        • 2021-03-03
        • 2016-02-18
        • 2021-08-14
        相关资源
        最近更新 更多