web-dev-qa-db-fra.com

Comment récupérer les données JSON de mysql?

J'ai les tables suivantes et leur relation. Je stocke des données JSON dans la table client_services. Est-ce un moyen de récupérer les valeurs JSON en utilisant la requête mysql. comme: 

select getJson("quota") as quota, client_id from client_services where service_id =1;    

OU 

Puis-je normaliser davantage la table client_services?

Prestations de service:

+----+-----------------------+--------------------------------------------------------+
| id | name                  | description                                            |
+----+-----------------------+--------------------------------------------------------+
|  1 | MailBox               |                                                        |
|  2 | SMS                   |                                                        |
|  3 | FTP                   |                                                        |
+----+-----------------------+--------------------------------------------------------+

service_features:

+----+------------+----------------------------------+------------------------+
| id | service_id | name                             | description            |
+----+------------+----------------------------------+------------------------+
| 10 |          1 | Forwarding                       | Forward Mail           |
| 11 |          1 | Archive                          | Archive Mail           |
| 12 |          1 | WebMail                          | NULL                   |
| 13 |          1 | IMAP                             | NULL                   |
| 14 |          2 | Web SMS                          | NULL                   |
+----+------------+----------------------------------+------------------------+

services clients:

+-----+-----------+------------+-------------------------------------------------------------------------------------------+
| id  | client_id | service_id | service_values                                                                            |
+-----+-----------+------------+-------------------------------------------------------------------------------------------+
| 100 |      1000 |          1 |{ "quota": 100000,"free_quota":20000,"total_accounts":200,"data_transfer":1000000}         |
| 101 |      1000 |          2 |{ "quota": 200 }                                                                           |
| 102 |      1000 |          3 |{ "data_transfer":1000000}                                                                 |
| 103 |      1001 |          1 |{ "quota": 1000000,"free_quota":2000,"total_accounts":200,"data_transfer":1000000}         |
| 104 |      1001 |          2 |{ "quota": 500 }                                                                           |
| 105 |      1002 |          2 |{ "quota": 600 }                                                                           |
+-----+-----------+------------+-------------------------------------------------------------------------------------------+

client_feature_mappers:

+-----+-------------------+--------------------+-----------+
| id  | client_service_id | service_feature_id | client_id |
+-----+-------------------+--------------------+-----------+
|10000|                100|                 10 |       1000|
|10001|                100|                 11 |       1000|
|10002|                100|                 12 |       1000|
|10003|                100|                 13 |       1000|
|10004|                101|                 14 |       1000|
|10005|                103|                 10 |       1001|
|10006|                101|                 11 |       1001|
|10007|                101|                 12 |       1001|
|10008|                101|                 13 |       1001|
|10009|                105|                 14 |       1002|
+-----+-------------------+--------------------+-----------+
16
pankaj ghadge

Étant donné que beaucoup de gens m'ont posé cette question personnellement, j'ai pensé que je donnerais à cette réponse une deuxième révision. Voici un Gist qui contient le code SQL complet avec SELECT, la migration et la création de vues et un violon sql en direct(disponibilité non garantie pour le violon).

Disons que vous avez une table (nommée: JSON_TABLE) comme ceci:

 ID   CITY        POPULATION_JSON_DATA
-----------------------------------------------------------------------
 1    LONDON      {"male" : 2000, "female" : 3000, "other" : 600}
 2    NEW YORK    {"male" : 4000, "female" : 5000, "other" : 500}

Pour sélectionner chaque champs JSON, vous pouvez faire:

SELECT 
    ID, CITY,
    json_extract(POPULATION_JSON_DATA, '$.male') AS POPL_MALE,
    json_extract(POPULATION_JSON_DATA, '$.female') AS POPL_FEMALE,
    json_extract(POPULATION_JSON_DATA, '$.other') AS POPL_OTHER
FROM JSON_TABLE;

qui résulte:

ID  CITY      POPL_MALE  POPL_FEMALE   POPL_OTHER 
-----------------------------------------------------------------
1   LONDON    2000       3000          600
2   NEW YORK  4000       5000          500

Cela peut être une opération coûteuse à exécuter en fonction de la taille de vos données et de la complexité de votre JSON. Je suggère de l'utiliser pour 

  1. Migration de la table vers la base de données fractionnée (Voir l’appendice 2-B de Gist) 
  2. Créez au moins une vue (voir l’annexe 2-C dans Gist) 

Faites attention à: Vous pouvez avoir json commençant par des guillemets doubles (stringifié): 

"{"male" : 2000, "female" : 3000, "other" : 600}"

Testé avec Mysql 5.7 sur Ubuntu et Mac OSX Sierra.

35
tika

Vous pouvez utiliser la fonction MySQL SUBSTRING_INDEX pour décomposer la chaîne JSON:

SELECT 
SUBSTRING_INDEX(
 SUBSTRING_INDEX(
  SUBSTRING_INDEX( service_values, 'quota', -1),
  '": ', -1),
 ' ', 1) AS quota,
client_id
FROM client_services
WHERE service_id=1;
4
pdolinaj

Tout d'abord, vous devez savoir que votre modèle ci-dessus n'est pas sous la première forme normale, ce qui signifie que vous ne devez avoir qu'une seule valeur dans chaque champ. Cependant, cette définition dépend des besoins de traitement de votre requête d'application. 

Donc, si tout ce que vous voulez, c'est mettre un tas de données JSON dans un champ et le renvoyer à l'application tel quel, alors tout va bien. Vous pouvez renvoyer l'intégralité des données JSON et laisser l'application sélectionner les attributs JSON de son choix. 

Mais si vous avez des requêtes, comme dans votre cas, ayant des critères ou des expressions de champ pour examiner les détails des données JSON, alors c'est définitivement impossible. Ce sera un cauchemar en termes de complexité des requêtes et de lenteur du traitement.

Vous pouvez bien entendu normaliser davantage vos tables pour remplacer complètement la structure de données JSON. Toutefois, si votre application nécessite un schéma flexible, peut-être la principale raison d'utiliser les bases de données NOSQL, mais que vous êtes coincé avec MySQL, il existe deux solutions:

a) utilisez MySQL 5.6 (ou MariaDB v. ??) pour le support NoSQL (je n’ai pas examiné les détails) http://www.computerworld.com/s/article/9236511/MySQL_5.6_tackles_NoSQL_competitors .__ Les colonnes dynamiques de .MariaDB: https://kb.askmonty.org/en/dynamic-columns/

b) utiliser mysql sans schéma explicite, voir ici pour une solution très bien faite, qui ne pose aucun problème d’évolutivité: http://backchannel.org/blog/friendfeed-schemaless-mysql

2
koriander

SET @a = '[{"x": 2, "y": "8"}, {"x": "3", "y": "7"}, {"x": "4", " y ": 6}] ';

SELECT * FROM JSON_TABLE ( @ A, "$ [*]" COLONNE ( Xval VARCHAR (100) PATH "$ .x", Yval VARCHAR (100 ) CHEMIN "$ .y" )) AS jt1;

0
Ivan DCosta