如何从MySQL中的动态键值对中提取JSON?

时间:2017-11-21 14:29:03

标签: mysql json

我有user_id和user_details的用户表。它包含字符串格式的JSON数据,如下所示:

[{"name":"question-1","value":"sachin","label":"Enter your name?"},
    {"name":"question-2","value":"abc@example.com","label":"Enter your email?"},
    {"name":"question-3","value":"xyz","label":"Enter your city?"}]

我尝试过使用json_extract但是如果json有如下所示的数据,它会返回结果:

{"name":"question-1","value":"sachin","label":"Enter your name?"}

然后将结果返回为

    Name    |     Label
question-1  |   Enter your name? 

预期成果: 我想从sql查询中的json中提取所有名称和标签。

实施例1: 请考虑我们在user_details列中包含以下数据,

[{"name":"question-1","value":"sachin","label":"Enter your name?"},
    {"name":"question-2","value":"abc@example.com","label":"Enter your email?"},
    {"name":"question-3","value":"xyz","label":"Enter your city?"}]

然后sql查询应该以下列格式返回结果,

    Name      |     Label
question-1    |  Enter your name?
question-2    |  Enter your email?
question-3    |  Enter your city?

如何在MySQL中使用JSON_EXTRACT获取此内容?

4 个答案:

答案 0 :(得分:0)

How to extract rows from a json array using the mysql udf json_extract 0.4.0?给出的另一个答案是用 common_schema 解析JSON。如果您不习惯复杂的SQL,那就非常棘手。

如果你知道该字段会给出多少元素,你可以按主题List all array elements of a MySQL JSON field中的建议创建一个自己的聚合表,但我想这不是你的情况。

然而,正如两个答案中所提到的,似乎更好的是不在SQL数据库中存储这样的json列表。也许你可以创建一个相关的表,每个字典包含一行,然后用外键将它链接到你的主表。

答案 1 :(得分:0)

我正在一份报告中,其中一列中有一个大的json数组列表。我修改了数据模型以将关系1存储到*而不是将所有内容存储在一个列中。为了完成这个过程,我不得不在存储过程中使用一段时间,因为我不知道最大大小:

DROP PROCEDURE IF EXISTS `test`;

DELIMITER #

CREATE PROCEDURE `test`()
PROC_MAIN:BEGIN
DECLARE numNotes int;
DECLARE c int;
DECLARE pos varchar(10);

SET c = 0;
SET numNotes = (SELECT 
ROUND (   
        (
            LENGTH(debtor_master_notes)
            - LENGTH( REPLACE ( debtor_master_notes, "Id", "") ) 
        ) / LENGTH("Id")        
    ) AS countt FROM debtor_master
order by countt desc Limit 1);

DROP TEMPORARY TABLE IF EXISTS debtorTable;
CREATE TEMPORARY TABLE debtorTable(debtor_master_id int(11), json longtext, note int);
WHILE(c <numNotes) DO
SET pos = CONCAT('$[', c, ']');
INSERT INTO debtorTable(debtor_master_id, json, note)
SELECT debtor_master_id, JSON_EXTRACT(debtor_master_notes, pos), c+1
FROM debtor_master
WHERE debtor_master_notes IS NOT NULL AND debtor_master_notes like '%[%' AND JSON_EXTRACT(debtor_master_notes, pos) IS NOT NULL AND JSON_EXTRACT(debtor_master_notes, pos) IS NOT NULL;
SET c = c + 1;
END WHILE;
SELECT * FROM debtorTable;
END proc_main #

DELIMITER ;

答案 2 :(得分:0)

我认为您没有使用表格。

SET @data = '[{"name":"question-1","value":"sachin","label":"Enter your name?"},
    {"name":"question-2","value":"abc@example.com","label":"Enter your email?"},
    {"name":"question-3","value":"xyz","label":"Enter your city?"}]';

SELECT JSON_EXTRACT(@data,'$[*].name') AS "name", JSON_EXTRACT(@data,'$[*].label') AS "label";

它将返回

name                                           |  label
["question-1", "question-2", "question-3"]     |  ["Enter your name?", "Enter your email?", "Enter your city?"]

根据您的表和列名称,SQL应该如下所示:

SELECT JSON_EXTRACT(user_details,'$[*].name') AS "name", JSON_EXTRACT(user_details,'$[*].label') AS "label" FROM user;

您可以通过对数组使用一些循环来匹配它们。我不知道这是否是最好的方法,但是它可以满足我的需求。

答案 3 :(得分:0)

您不使用JSON_EXTRACT()。您使用JSON_TABLE()

mysql> create table mytable ( id serial primary key, data json);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into mytable set data = '[{"name":"question-1","value":"sachin","label":"Enter your name?"},
    '>     {"name":"question-2","value":"abc@example.com","label":"Enter your email?"},
    '>     {"name":"question-3","value":"xyz","label":"Enter your city?"}]';
Query OK, 1 row affected (0.00 sec)

mysql> SELECT j.* FROM mytable,
  JSON_TABLE(data, '$[*]' COLUMNS (
    name VARCHAR(20) PATH '$.name', 
    label VARCHAR(50) PATH '$.label'
  )) AS j;
+------------+-------------------+
| name       | label             |
+------------+-------------------+
| question-1 | Enter your name?  |
| question-2 | Enter your email? |
| question-3 | Enter your city?  |
+------------+-------------------+

JSON_TABLE()需要MySQL 8.0.4或更高版本。如果您至少未运行该版本,则必须进行升级。

老实说,如果您需要访问各个字段,那么将数据存储在普通列中并避免使用JSON即可。