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 (El equipo de MySQL ha agregó 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/
)JSON_TABLE
función.)