【问题标题】:How to convert json MySQL data into rows and column如何将json MySQL数据转换为行和列
【发布时间】:2022-02-23 17:26:30
【问题描述】:

我有这样的 mysql 表,其中包含 id 和 json 类型列:

id value
1 {"sys": "20", "dia": "110"}
2 {"bpm": "200"}
3 {"bpm": "123", "sys": "1", "dia": ""}

现在,我想要一个 MySQL 查询,其中的数据应如下所示,其中 id、val1 将包含 json 数据的键,而 val2 将包含各个键的值:

id val1 val2
1 sys 20
1 dia 110
2 bpm 200
3 bpm 123
3 sys 1
3 dia

注意:我使用的是 MySQL 5.7 版本,JSON 对象内的键不固定。可以是任意数字。

我想知道如何使用 MySQL 查询来实现这一点

提前致谢!!!

【问题讨论】:

  • 似乎将数据库设计为一个更好的主意,因为应该设计一个关系数据库。将数据库设计重构为更适合关系模型的东西是否为时已晚
  • JSON(JavaScript 对象表示法)通常由编程语言使用,而不是查询语言。所以,是的,你应该使用 MySQL 查询来检索和存储数据,但是为了解开 JSON,我会使用 PHP/Python/C/etc 之类的东西。 MySQL 确实有some support for JSON,也许这就足够了,但我对此表示怀疑。
  • 我有这样的 mysql 表,其中包含 id 和 json 类型列: 显示的值可以是存储在 string-datatype 列中的 JSON 值,而不是存储在 JSON-datatype 列中。 val1 将包含 json 数据的键,val2 将包含各个键的值...我想知道如何使用 MySQL 查询来实现这一点 在您的版本上,这只能在迭代存储过程中执行.要在单个查询中执行此操作,您必须至少将服务器升级到 8.0.4。
  • 啊。当可以在数据库列中存储任意序列化对象(JSON 对象)时,这是一个噩梦般的数据库设计示例。请添加一个包含 idvital_namevalue 列的生命体征表。请注意,您还可以向生命体征添加时间戳或其他属性。请不要将 JSON 放在您的表列中,至少不要将您希望 MySQL 操作的数据放在其中。

标签: mysql denormalization mysql-json


【解决方案1】:
CREATE TABLE test (id INT, value JSON);
INSERT INTO test VALUES
(1,   '{"sys": "20", "dia": "110"}'),
(2,   '{"bpm": "200"}'),
(3,   '{"bpm": "123", "sys": "1", "dia": ""}');
SELECT id, CAST(value AS CHAR) value FROM test;
id value
1 {"dia": "110", "sys": "20"}
2 {"bpm": "200"}
3 {"bpm": "123", "dia": "", "sys": "1"}
CREATE PROCEDURE parse_json ()
BEGIN
DECLARE counter INT DEFAULT 0;
CREATE TEMPORARY TABLE tmp1 (id INT, all_keys JSON)
SELECT id, JSON_KEYS(value) all_keys
FROM test;
CREATE TEMPORARY TABLE tmp2 (id INT, one_key VARCHAR(255)) ENGINE = Memory;
REPEAT
    INSERT INTO tmp2
    SELECT id, JSON_EXTRACT(all_keys, CONCAT('$[',counter,']')) one_key
    FROM tmp1
    HAVING one_key IS NOT NULL;
    SET counter := counter + 1;
UNTIL NOT ROW_COUNT() END REPEAT;
SELECT id, 
       CAST(JSON_UNQUOTE(tmp2.one_key) AS CHAR) val1, 
       CAST(JSON_UNQUOTE(JSON_EXTRACT(test.value, CONCAT('$.', tmp2.one_key))) AS CHAR) val2
FROM test
JOIN tmp2 USING (id)
ORDER BY 1,2;
DROP TEMPORARY TABLE tmp1;
DROP TEMPORARY TABLE tmp2;
END
CALL parse_json
id val1 val2
1 dia 110
1 sys 20
2 bpm 200
3 bpm 123
3 dia
3 sys 1

db小提琴here

如果具有 JSON 值的列的数据类型是 VARCHAR/TEXT,则数据应该在 JSON 值中包含重复的键。

【讨论】:

    【解决方案2】:

    我能够找到下面的 sql 查询,它将返回它的数据:

    select id as Id
    ,JSON_UNQUOTE(JSON_EXTRACT(JSON_KEYS(value), CONCAT('$[', idx , ']'))) as val1
    ,JSON_UNQUOTE(JSON_EXTRACT(ic1.value, CONCAT('$.',JSON_EXTRACT(JSON_KEYS(value), CONCAT('$[', idx , ']'))))) as val2
    from test as ic1
    INNER JOIN (  
       SELECT 0 as idx UNION ALL 
       SELECT 1 as idx UNION ALL 
       SELECT 2 as idx UNION ALL 
       SELECT 3 as idx UNION ALL
       SELECT 4 as idx UNION ALL 
       SELECT 5 as idx UNION ALL
       SELECT 6 as idx UNION ALL
       SELECT 7 as idx UNION ALL
       SELECT 8 
      ) AS Indices 
    ON Indices.idx < JSON_LENGTH(JSON_KEYS(value))
    ORDER BY id;
    

    【讨论】:

      猜你喜欢
      • 2016-12-11
      • 2015-11-10
      • 1970-01-01
      • 1970-01-01
      • 2012-01-01
      • 2013-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多