Mysql
 sql >> Base de données >  >> RDS >> Mysql

Convertir le tableau JSON dans MySQL en lignes

Il est vrai que ce n'est pas une bonne idée de dénormaliser en JSON, mais parfois vous devez gérer des données JSON, et il existe un moyen d'extraire un tableau JSON en lignes dans une requête.

L'astuce consiste à effectuer une jointure sur une table d'index temporaire ou en ligne, ce qui vous donne une ligne pour chaque valeur non nulle dans un tableau JSON. C'est-à-dire que si vous avez une table avec les valeurs 0, 1 et 2 que vous joignez à un tableau JSON "fish" avec deux entrées, alors fish[0] correspond à 0, ce qui donne une ligne, et fish1 correspond à 1, ce qui donne une deuxième ligne, mais fish[2] est nul, il ne correspond donc pas à 2 et ne produit pas de ligne dans la jointure. Vous avez besoin d'autant de nombres dans la table d'index que la longueur maximale de n'importe quel tableau dans vos données JSON. C'est un peu un hack, et c'est à peu près aussi douloureux que l'exemple de l'OP, mais c'est très pratique.

Exemple (nécessite MySQL 5.7.8 ou version ultérieure) :

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;

Le résultat est :

+---------+-----+---------+
| rec_num | idx | fishes  |
+---------+-----+---------+
|       1 |   0 | "red"   |
|       1 |   1 | "blue"  |
|       2 |   0 | "one"   |
|       2 |   1 | "two"   |
|       2 |   2 | "three" |
+---------+-----+---------+

Il semble que l'équipe MySQL puisse ajouter un JSON_TABLE fonction dans MySQL 8 pour rendre tout cela plus facile. (http://mysqlserverteam.com/mysql-8-0 -labs-json-aggregation-functions/ ) (L'équipe MySQL a ajouté un JSON_TABLE fonction.)