Det är sant att det inte är en bra idé att avnormalisera till JSON, men ibland måste du hantera JSON-data, och det finns ett sätt att extrahera en JSON-array i rader i en fråga.
Tricket är att utföra en join på en temporär eller inline-tabell med index, vilket ger dig en rad för varje icke-nullvärde i en JSON-array. Dvs om du har en tabell med värdena 0, 1 och 2 som du kopplar till en JSON-array "fish" med två poster, matchar fish[0] 0, vilket resulterar i en rad, och fish1 matchar 1, vilket resulterar i en andra rad, men fish[2] är null så den matchar inte 2:an och ger inte en rad i sammanfogningen. Du behöver lika många siffror i indextabellen som maxlängden för en array i din JSON-data. Det är lite av ett hack, och det är ungefär lika smärtsamt som OP:s exempel, men det är väldigt praktiskt.
Exempel (kräver MySQL 5.7.8 eller senare):
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;
Resultatet är:
+---------+-----+---------+
| rec_num | idx | fishes |
+---------+-----+---------+
| 1 | 0 | "red" |
| 1 | 1 | "blue" |
| 2 | 0 | "one" |
| 2 | 1 | "two" |
| 2 | 2 | "three" |
+---------+-----+---------+
Det verkar som att MySQL-teamet kan lägga till en (MySQL-teamet har lade till en JSON_TABLE
funktion i MySQL 8 för att göra allt detta enklare. (http://mysqlserverteam.com/mysql-8-0 -labs-json-aggregation-functions/
)JSON_TABLE
funktion.)