mysql解析json字符串相關問題


很多時候,我們需要在sql里面直接解析json字符串。這里針對mysql5.7版本的分水嶺進行區分。

1.對於mysql5.7以上版本

    使用mysql的內置函數JSON_EXTRACT(column, '$.key'),這個函數有兩個參數,第一個參數column代表json列的列名;第二個參數key代表json字符串中的某一個key。

    SELECT JSON_EXTRACT('{"priceTag":"員工/合作關鍵人","priceDiscount":"90"}', '$.priceDiscount') AS '定價折扣';

    對於簡單的json字符串肯定是可以解析成功,但是對於嵌套數組的沒試過。

2.對於mysql5.7以下版本

    只能充分發揮已有函數的功能去截取實現,無論實現方式是存儲過程還是簡單的sql語句,其原理都是一樣的。

    第一步,將所有的花括號的閉括號'}'替換成英文逗號',';第二步,獲取key的坐標keyIndex和長度keyLength;第三步,獲取以key為起點,第一個英文逗號','的坐標symbolIndex;第四步,使用substring截取字符串SUBSTRING(targetJsonStr, keyIndex + keyLength, symbolIndex - keyIndex - keyLength);第五步,使用replace將雙引號'"'替換成空字符串'',完工。

    示例:從{"priceTag": "員工/合作關鍵人","priceDiscount": "90"}中獲取priceDiscount的值。

SELECT
    REPLACE(
	-- SUBSTRING(s,n,len)
	-- 帶有 len 參數的格式,從字符串 s 返回一個長度同 len 字符相同的子字符串,起始於位置 n。
        SUBSTRING(
            REPLACE(
                '{"priceTag":"員工/合作關鍵人","priceDiscount":"90"}' ,
                '}' ,
                ','
            ) , -- s 將初始字段中的有括號替換成','號
        -- LOCATE(substr,str)
	    -- 返回字符串substr在字符串str中第一次出現的位置從1開始計數 。
            LOCATE(
                'priceDiscount":' ,
                REPLACE(
                    '{"priceTag":"員工/合作關鍵人","priceDiscount":"90"}' ,
                    '}' ,
                    ','
                )
            ) + CHAR_LENGTH('priceDiscount":') ,-- n 起始位置
            LOCATE(
                ',' ,
                REPLACE(
                    '{"priceTag":"員工/合作關鍵人","priceDiscount":"90"}' ,
                    '}' ,
                    ','
                ) ,
                LOCATE(
                    'priceDiscount":' ,
                    REPLACE(
                        '{"priceTag":"員工/合作關鍵人","priceDiscount":"90"}' ,
                        '}' ,
                        ','
                    )
                ) + CHAR_LENGTH('priceDiscount":') -- n后的第一個','號在 s 中所在的位置
            ) -(
                LOCATE(
                    'priceDiscount":' ,
                    REPLACE(
                        '{"priceTag":"員工/合作關鍵人","priceDiscount":"90"}' ,
                        '}' ,
                        ','
                    )
                ) + CHAR_LENGTH('priceDiscount":')
            ) -- 計算出了key值對應的value值的長度
        ) ,
        '"' ,
        ''
    ) AS '定價折扣'; 

文字描述:

1.先將原始字符串的右'}' 替換成 ','   

2.計算出key值在步驟1中的位置,當做字段截取的起始位置

3.計算出key值右邊最近的一個','號在步驟1中的位置  - 步驟2的位置 = key值對應的value值即字段截取長度

4.截取value值兩邊的雙引號,即得出value值

參考:https://www.jianshu.com/p/513acedf436d

     https://blog.csdn.net/helloxiaozhe/article/details/86571387

相關函數介紹

LOCATE函數

語法 一:

LOCATE(substr,str)

返回字符串substr在字符串str中第一次出現的位置從1開始計數 。

 如:

SELECT LOCATE("a","abca")

查詢結果:

 

語法二:

LOCATE(substr,str,pos)

返回字符串substr從pos往后數在字符串str中第一次出現的位置從1開始計數 。

 如:

SELECT LOCATE("a","abca",2)  

查詢結果:

注:如果str、substr中任意一個字段為null則查詢結果為null

  如果substr在str中不存在則返回0

 

SUBSTRING函數

MYSQL中獲取子串函數 SUBSTRING(s,n,len) 帶有 len 參數的格式,從字符串 s 返回一個長度同 len 字符相同的子字符串,起始於位置 n。

也可能對 n 使用一個負值。假若這樣,則子字符串的位置起始於字符串結尾的第 n 個字符,即倒數第 n 個字符,而不是字符串的開頭位置。

 參考:http://c.biancheng.net/mysql/substring.html

 

CHAR_LENGTH函數

返回函數內字符串的長度

如:

CHAR_LENGTH('priceDiscount":')

查詢結果: 

 

踩坑背景:公司使用了MongoDB數據庫存放數據,但是我所做的通用統計服務數據又存放在mysql內,所以需要MongoDB的數據往mysql導入,如果是簡單的數據倒是沒啥,但是這個json數據就有點難搞了。

比如上面的例子:他的key值是固定的,順序可能也一致。MongoDB里面的數據就不一樣了

舉幾個例子:

{"lightspot":"問題解決效率高","scotoma":"1.未查客戶逾期情況2.未核實客戶身份"}

{"scotoma":"未咨詢匯款人"}

{"lightspot":"核實客戶身份;問題處理快"}

{"scotoma":"后台操作不應說出(我看下是哪個客戶)","lightspot":"1.規范用語2.問題解決思路清晰"}

順序不一致,key值不一定全

 

SELECT  
	REPLACE(
	  substr(
		REPLACE(ifnull(`b`.`comment`, ''),'}', ','), -- 原始字段
		locate('scotoma":', REPLACE(ifnull(`b`.`comment`, ''), '}', ','))+ char_length('scotoma":'), -- 起始位置
		IF(locate('scotoma":',
			REPLACE(ifnull(`b`.`comment`, ''),
						      '}',
					              ',')
			) <> 0, -- 判定key值是否存在
		locate(',',
		      REPLACE(ifnull(`b`.`comment`, ''), '}', ','),
		      locate('scotoma":', REPLACE(ifnull(`b`.`comment`, ''), '}', ','))
		      + char_length('scotoma":')
		      ) - (locate('scotoma":', REPLACE(ifnull(`b`.`comment`, ''), '}', ',')) + char_length('scotoma":')) -- 有就正常取值獲取取值長度
		, 0) -- 沒有就取長度0
	), -- 獲取value內容
	'"',
	''
	)
FROM ctr_new_db.cti_quality_judgement b

 

注:如果要運行我的這段sql只需要將sql中的`b`.`comment`替換成我上面舉例的四個字符串中的任意一個即可

文字描述:

1.先將原始字符串的右'}' 替換成 ','   

2.計算出key值在步驟1中的位置,當做字段截取的起始位置

3.判定key值在這個json中是否存在,存在則按照之前的計算邏輯獲取value值的大小,不存在則取0

4.截取value值兩邊的雙引號,即得出value值


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM