2013-03-29 141 views
7

我有以下表格及其關係。我將json數據存儲在client_services表中。他們有沒有辦法使用mysql查詢來檢索JSON值。像:如何從mysql中檢索JSON數據?

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

OR

我能正常化client_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| 
+-----+-------------------+--------------------+-----------+ 
+1

爲什麼要將原始JSON存儲在表中?以更邏輯的格式存儲數據並在堆棧中的更高級別構建JSON會更有意義嗎? – david99world

回答

15

由於很多人親自向我提出這個問題,我想我會給這個答案第二次修訂。這裏是a gist that has the complete SQL with SELECT, Migration and View Creationa live sql fiddle(可用性不保證爲小提琴)

比方說,你有表(名爲:JSON_TABLE)是這樣的:

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

導致:

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進行測試。

+0

(加1)「僅用於數據遷移」 – user3581203

1

數據庫用於存儲和檢索數據,而不是格式化數據。 MySQL以表格的形式輸出東西,這就是它的工作原理。所以如果你想擁有JSON,你需要在代碼中自己將這個表格數據轉換爲JSON。

+0

我需要mysql查詢來檢索json數據,因爲像dovecot(Imap,pop服務器)這樣的服務器直接向mysql查詢,否則我通過代碼完成它。我遇到過一些Mysql UDF,比如http://blog.kazuhooku.com/2011/09/mysqljson-mysql-udf-for-parsing-json.html。值得安裝嗎? –

+0

@ pankajghadge這是一種奇怪的架構,顯然你正在用錯誤的工具解決你的問題。但是你可以編寫將表格數據格式化爲JSON的mysql程序,這並不困難。 – Andrey

+0

我沒有編寫mysql函數的經驗。我是關於進一步標準化表的事情,但它會增加查詢輸出時間。 –

2

首先,您應該知道您的模型不在第一範式中,這意味着您應該在每個字段中只有一個值。但是,此定義取決於您的應用程序查詢處理需求。

因此,如果你只想把一堆JSON數據放在一個字段中,並按原樣返回給應用程序,那就沒問題。您可以返回整個JSON數據,並讓應用程序選擇它想要的JSON屬性。

但是,如果你有查詢,就像你的情況一樣,有標準或字段表達式來查看JSON數據的細節,那麼這絕對是一個不行。這將是查詢複雜性和緩慢處理的噩夢。

你當然可以進一步標準化你的表來完全替代JSON數據結構。但是,如果您的應用程序需要靈活的模式,也許是使用NOSQL DB的主要原因,但您堅持使用MySQL,有兩種解決方案:

a)使用MySQL 5.6(或MariaDB v。??)支持(我還沒有研究細節)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

3

您可以使用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;