sql >> Base de Datos >  >> RDS >> Mysql

Convierta la matriz JSON en MySQL en filas

Es cierto que no es una buena idea desnormalizar a JSON, pero a veces es necesario manejar datos JSON y hay una forma de extraer una matriz JSON en filas en una consulta.

El truco consiste en realizar una unión en una tabla de índices temporal o en línea, lo que le proporciona una fila para cada valor no nulo en una matriz JSON. Es decir, si tiene una tabla con los valores 0, 1 y 2 que une a una matriz JSON "fish" con dos entradas, entonces fish[0] coincide con 0, lo que da como resultado una fila, y fish1 coincide con 1, lo que da como resultado una segunda fila, pero fish[2] es nulo, por lo que no coincide con el 2 y no produce una fila en la unión. Necesita tantos números en la tabla de índice como la longitud máxima de cualquier matriz en sus datos JSON. Es un truco y es tan doloroso como el ejemplo del OP, pero es muy útil.

Ejemplo (requiere MySQL 5.7.8 o 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;

El resultado es:

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

Parece que el equipo de MySQL puede agregar un JSON_TABLE función en MySQL 8 para hacer todo esto más fácil. (http://mysqlserverteam.com/mysql-8-0 -labs-json-agregación-funciones/ ) (El equipo de MySQL ha agregó un JSON_TABLE función.)