37

我有下表及其关系。我将 JSON 数据存储在 client_services 表中。他们有什么方法可以使用 MySQL 查询来检索 JSON 值,如下所示:

SELECT getJson("quota") as quota,
       client_id
FROM client_services
WHERE service_id = 1;     

或者我可以进一步规范 client_services 表吗?

Services

+----+-----------------------+--------------------------------------------------------+
| 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                   |
+----+------------+----------------------------------+------------------------+

client_services

+-----+-----------+------------+-------------------------------------------------------------------------------------------+
| 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|
+-----+-------------------+--------------------+-----------+
4

5 回答 5

67

由于很多人亲自向我提出过​​这个问题,我想我会给这个答案第二次修改。这是一个要点,其中包含带有 SELECT、迁移和视图创建的完整 SQL以及一个实时 sql fiddle (fiddle 不保证可用性)

假设您有这样的表(名为:TBL_JSON):

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

要选择每个 json 字段,您可以执行以下操作:

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 TBL_JSON;

结果:

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

根据您的数据大小和 json 复杂性,这可能是一项昂贵的操作。我建议将其用于

  1. 将表迁移到拆分数据库(参见要点中的附录 2-B)
  2. 至少创建一个视图 (参见要点中的附录 2-C)

注意:您可能有以双引号(字符串化)开头的json:

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

在 Ubuntu 和 Mac OSX Sierra 上使用 Mysql 5.7 进行测试。

于 2016-07-25T00:31:42.340 回答
4

您可以使用 MySQL 函数 SUBSTRING_INDEX 来分解 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;
于 2014-02-24T16:13:29.017 回答
2

首先,您应该知道上面的模型不是第一范式,这意味着您应该在每个字段中只有一个值。但是,此定义取决于您的应用程序查询处理需求。

因此,如果您只想将一堆 JSON 数据放在一个字段中并按原样返回给应用程序,那就没问题了。您可以返回整个 JSON 数据并让应用程序选择它想要的 JSON 属性。

但是,如果您有查询,如您的情况,有条件或字段表达式来查看 JSON 数据的详细信息,那么这绝对是不行的。这将是查询复杂性和处理缓慢的噩梦。

您当然可以进一步规范化您的表以完全替换 JSON 数据结构。但是,如果您的应用程序需要灵活的模式,这可能是使用 NOSQL 数据库的主要原因,但您却被 MySQL 卡住了,有两种解决方案:

a) 使用 MySQL 5.6 (或 MariaDB v.??) 支持 NoSQL (我还没有查看详细信息) http://www.computerworld.com/s/article/9236511/MySQL_5.6_tackles_NoSQL_competitors MariaDB 的动态列:https: //kb.askmonty.org/en/dynamic-columns/

b) 在没有显式模式的情况下使用 mysql,请参阅此处了解一个非常出色的解决方案,它没有可扩展性问题:http ://backchannel.org/blog/friendfeed-schemaless-mysql

于 2013-03-30T21:17:04.393 回答
2

是的,您绝对可以使用 MySQL 查询(使用 JSON_EXTRACT() 函数)检索 JSON 值。

让我们把你的表包含 json (client_services这里的表):

+-----+-----------+------------+-------------------------------------------------------------------------------------------+
| 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 }                                                                           |
+-----+-----------+------------+-------------------------------------------------------------------------------------------+

要选择每个 JSON 字段,请运行以下查询:

SELECT 
    id, client_id, service_id,
    json_extract(service_values, '$.quota') AS quota,
    json_extract(service_values, '$.free_quota') AS free_quota,
    json_extract(service_values, '$.total_accounts') AS total_accounts,
    json_extract(service_values, '$.data_transfer') AS data_transfer
FROM client_services;

所以输出将是:

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

希望这可以帮助!

于 2020-06-23T06:31:26.473 回答
0
SET @a = '[{"x":2,"y":"8"},{"x":"3","y":"7"},{"x":"4","y":6}]' ;

SELECT *
FROM
JSON_TABLE(
@a,
"$[*]" COLUMNS(
xval VARCHAR(100) PATH "$.x",
yval VARCHAR(100) PATH "$.y"
)) AS  jt1;
于 2018-11-15T11:20:54.697 回答