Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Konvertieren Sie das JSON-Array in MySQL in Zeilen

Es stimmt, dass es keine gute Idee ist, in JSON zu denormalisieren, aber manchmal müssen Sie mit JSON-Daten umgehen, und es gibt eine Möglichkeit, ein JSON-Array in Zeilen in einer Abfrage zu extrahieren.

Der Trick besteht darin, einen Join für eine temporäre oder Inline-Tabelle mit Indizes durchzuführen, wodurch Sie eine Zeile für jeden Nicht-Null-Wert in einem JSON-Array erhalten. Das heißt, wenn Sie eine Tabelle mit den Werten 0, 1 und 2 haben, die Sie mit einem JSON-Array „Fisch“ mit zwei Einträgen verbinden, dann stimmt Fisch[0] mit 0 überein, was zu einer Zeile führt, und Fisch1 stimmt mit 1 überein, was zu einer zweiten Zeile führt, aber fish[2] ist null, sodass es nicht mit 2 übereinstimmt und keine Zeile im Join erzeugt. Sie benötigen so viele Zahlen in der Indextabelle wie die maximale Länge eines beliebigen Arrays in Ihren JSON-Daten. Es ist ein bisschen wie ein Hack, und es ist ungefähr so ​​schmerzhaft wie das Beispiel des OP, aber es ist sehr praktisch.

Beispiel (erfordert MySQL 5.7.8 oder höher):

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;

Das Ergebnis ist:

+---------+-----+---------+
| rec_num | idx | fishes  |
+---------+-----+---------+
|       1 |   0 | "red"   |
|       1 |   1 | "blue"  |
|       2 |   0 | "one"   |
|       2 |   1 | "two"   |
|       2 |   2 | "three" |
+---------+-----+---------+

Es sieht so aus, als würde das MySQL-Team eine JSON_TABLE hinzufügen Funktion in MySQL 8, um all dies einfacher zu machen. (http://mysqlserverteam.com/mysql-8-0 -labs-json-aggregation-functions/ ) (Das MySQL-Team hat JSON_TABLE hinzugefügt Funktion.)