Het is waar dat het geen goed idee is om te denormaliseren naar JSON, maar soms moet je JSON-gegevens verwerken en er is een manier om een JSON-array in rijen in een query te extraheren.
De truc is om een join uit te voeren op een tijdelijke of inline-tabel met indexen, die u een rij geeft voor elke niet-null-waarde in een JSON-array. D.w.z. als je een tabel hebt met de waarden 0, 1 en 2 die je samenvoegt met een JSON-array "fish" met twee items, dan komt fish[0] overeen met 0, wat resulteert in één rij, en fish1 komt overeen met 1, wat resulteert in een tweede rij, maar fish[2] is null, dus het komt niet overeen met de 2 en produceert geen rij in de join. U hebt net zoveel getallen in de indextabel nodig als de maximale lengte van een array in uw JSON-gegevens. Het is een beetje een hack, en het is ongeveer net zo pijnlijk als het voorbeeld van de OP, maar het is erg handig.
Voorbeeld (vereist MySQL 5.7.8 of hoger):
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;
Het resultaat is:
+---------+-----+---------+
| rec_num | idx | fishes |
+---------+-----+---------+
| 1 | 0 | "red" |
| 1 | 1 | "blue" |
| 2 | 0 | "one" |
| 2 | 1 | "two" |
| 2 | 2 | "three" |
+---------+-----+---------+
Het lijkt erop dat het MySQL-team een (Het MySQL-team heeft een JSON_TABLE
kan toevoegen functie in MySQL 8 om dit allemaal gemakkelijker te maken. (http://mysqlserverteam.com/mysql-8-0 -labs-json-aggregation-functions/
)JSON_TABLE
toegevoegd
functie.)