Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Converter matriz JSON no MySQL para linhas


É verdade que não é uma boa ideia desnormalizar em JSON, mas às vezes você precisa lidar com dados JSON e há uma maneira de extrair uma matriz JSON em linhas em uma consulta.

O truque é realizar uma junção em uma tabela de índices temporária ou em linha, que fornece uma linha para cada valor não nulo em uma matriz JSON. Ou seja, se você tiver uma tabela com valores 0, 1 e 2 que você une a uma matriz JSON “fish” com duas entradas, fish[0] corresponde a 0, resultando em uma linha, e fish1 corresponde a 1, resultando em uma segunda linha, mas fish[2] é nulo, portanto, não corresponde ao 2 e não produz uma linha na junção. Você precisa de tantos números na tabela de índice quanto o comprimento máximo de qualquer matriz em seus dados JSON. É um pouco hack, e é tão doloroso quanto o exemplo do OP, mas é muito útil.

Exemplo (requer MySQL 5.7.8 ou posterior):
CREATE TABLE t1 (rec_num INT, jdoc JSON);
INSERT INTO t1 VALUES 
  (1, '{"fish": ["red", "blue"]}'), 
  (2, '{"fish": ["one", "two", "three"]}');

SELECT
  rec_num,
  idx,
  JSON_EXTRACT(jdoc, CONCAT('$.fish[', idx, ']')) AS fishes
FROM t1
  -- Inline table of sequential values to index into JSON array
JOIN ( 
  SELECT  0 AS idx UNION
  SELECT  1 AS idx UNION
  SELECT  2 AS idx UNION
  -- ... continue as needed to max length of JSON array
  SELECT  3
  ) AS indexes
WHERE JSON_EXTRACT(jdoc, CONCAT('$.fish[', idx, ']')) IS NOT NULL
ORDER BY rec_num, idx;

O resultado é:
+---------+-----+---------+
| rec_num | idx | fishes  |
+---------+-----+---------+
|       1 |   0 | "red"   |
|       1 |   1 | "blue"  |
|       2 |   0 | "one"   |
|       2 |   1 | "two"   |
|       2 |   2 | "three" |
+---------+-----+---------+

Parece que a equipe do MySQL pode adicionar um JSON_TABLE função no MySQL 8 para tornar tudo isso mais fácil. (http://mysqlserverteam.com/mysql-8-0 -labs-json-aggregation-functions/ ) (A equipe do MySQL tem adicionou um JSON_TABLE função.)