Je pravda, že není dobrý nápad denormalizovat na JSON, ale někdy se potřebujete vypořádat s daty JSON a existuje způsob, jak extrahovat pole JSON do řádků v dotazu.
Trik je provést spojení na dočasné nebo vložené tabulce indexů, což vám poskytne řádek pro každou nenulovou hodnotu v poli JSON. To znamená, že pokud máte tabulku s hodnotami 0, 1 a 2, kterou připojíte k poli JSON „fish“ se dvěma položkami, pak fish[0] odpovídá 0, výsledkem je jeden řádek a fish1 odpovídá 1, výsledkem je druhý řádek, ale fish[2] je null, takže neodpovídá 2 a nevytváří řádek ve spojení. Potřebujete tolik čísel v indexové tabulce, jako je maximální délka libovolného pole v datech JSON. Je to trochu hack a je to asi tak bolestivé jako příklad OP, ale je to velmi praktické.
Příklad (vyžaduje MySQL 5.7.8 nebo novější):
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;
Výsledek je:
+---------+-----+---------+
| rec_num | idx | fishes |
+---------+-----+---------+
| 1 | 0 | "red" |
| 1 | 1 | "blue" |
| 2 | 0 | "one" |
| 2 | 1 | "two" |
| 2 | 2 | "three" |
+---------+-----+---------+
Zdá se, že tým MySQL může přidat (Tým MySQL má přidal JSON_TABLE
funkce v MySQL 8, aby to vše bylo jednodušší. (http://mysqlserverteam.com/mysql-8-0 -labs-json-aggregation-functions/
)JSON_TABLE
funkce.)