È 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 (Il team MySQL ha aggiunto un JSON_TABLE
funzione in MySQL 8 per rendere tutto più semplice. (http://mysqlserverteam.com/mysql-8-0 -labs-json-aggregation-functions/
)JSON_TABLE
funzione.)