Mysql
 sql >> Database >  >> RDS >> Mysql

Converti l'array JSON in MySQL in righe

È vero che non è una buona idea denormalizzare in JSON, ma a volte è necessario gestire i dati JSON e c'è un modo per estrarre un array JSON in righe in una query.

Il trucco consiste nell'eseguire un join su una tabella di indici temporanea o inline, che fornisce una riga per ogni valore non nullo in un array JSON. Ad esempio, se hai una tabella con valori 0, 1 e 2 che unisci a un array JSON "fish" con due voci, fish[0] corrisponde a 0, risultando in una riga, e fish1 corrisponde a 1, risultando in una seconda riga, ma fish[2] è nullo quindi non corrisponde a 2 e non produce una riga nel join. Hai bisogno di tanti numeri nella tabella dell'indice quanto la lunghezza massima di qualsiasi array nei tuoi dati JSON. È un po' un trucco ed è doloroso quanto l'esempio dell'OP, ma è molto utile.

Esempio (richiede MySQL 5.7.8 o successivo):

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;

Il risultato è:

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

Sembra che il team MySQL possa aggiungere un JSON_TABLE funzione in MySQL 8 per rendere tutto più semplice. (http://mysqlserverteam.com/mysql-8-0 -labs-json-aggregation-functions/ ) (Il team MySQL ha aggiunto un JSON_TABLE funzione.)