如何将jsonMySQL数据转换成行和列
How to convert json MySQL data into rows and column
我有 mysql table 这样的包含 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 查询
实现此目的
提前致谢!!!
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<>fiddle here
如果具有 JSON 值的列的数据类型为 VARCHAR/TEXT,则数据应 NOT 包含 JSON 值中的重复键。
我能够找到下面的 sql 查询,它将 return 我的数据:
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;
我有 mysql table 这样的包含 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 查询
实现此目的提前致谢!!!
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<>fiddle here
如果具有 JSON 值的列的数据类型为 VARCHAR/TEXT,则数据应 NOT 包含 JSON 值中的重复键。
我能够找到下面的 sql 查询,它将 return 我的数据:
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;