MySql字符串拆分實現split功能(字段分割轉列)
需求描述
數據庫中 num字段值為:
實現的效果:需要將一行數據變成多行
實現的sql
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('7654,7698,7782,7788',',',help_topic_id+1),',',-1) AS num FROM mysql.help_topic WHERE help_topic_id < LENGTH('7654,7698,7782,7788')-LENGTH(REPLACE('7654,7698,7782,7788',',',''))+1
案例演示
CREATE TABLE `company` ( `id` int(20) DEFAULT NULL, `name` varchar(100) DEFAULT NULL, `shareholder` varchar(100) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `company` VALUES ('1', '阿裡巴巴', '馬雲'); INSERT INTO `company` VALUES ('2', '淘寶', '馬雲,孫正義');
1、原始數據演示
2、處理結果演示
3、sql語句
SELECT a.id , a.NAME , substring_index(substring_index(a.shareholder, ',', b.help_topic_id + 1), ',', - 1) AS shareholder FROM company a INNER JOIN mysql.help_topic b ON b.help_topic_id < (length(a.shareholder) - length(REPLACE(a.shareholder, ',', '')) + 1)
涉及的知識點如下:
字符串拆分: SUBSTRING_INDEX(str, delim, count)
參數解說 解釋
str 需要拆分的字符串
delim 分隔符,通過某字符進行拆分
count 當 count 為正數,取第 n 個分隔符之前的所有字符; 當 count 為負數,取倒數第 n 個分隔符之後的所有字符。
舉例
(1)獲取第2個以逗號為分隔符之前的所有字符。
SELECT SUBSTRING_INDEX('7654,7698,7782,7788',',',2);
(2)獲取最後一個到倒數第2個以逗號分隔符之後的所有字符
SELECT SUBSTRING_INDEX('7654,7698,7782,7788',',',-2);
所以,我們的核心代碼中的 -1 ,就是獲取以逗號為分隔符的最後一個值;也就是7788
替換函數:replace( str, from_str, to_str)
參數名 解釋
str 需要進行替換的字符串
from_str 需要被替換的字符串
to_str 需要替換的字符串
舉例
將分隔符逗號替換為空。
SELECT REPLACE('7654,7698,7782,7788',',','');
獲取字符串長度:LENGTH( str )
參數名 解釋
str 需要計算長度的字符串
獲取 ‘7654,7698,7782,7788’ 字符串的長度
SELECT LENGTH('7654,7698,7782,7788')
實現的原理解析
【4.1】 實現sql
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('7654,7698,7782,7788',',',help_topic_id+1),',',-1) AS num FROM mysql.help_topic WHERE help_topic_id < LENGTH('7654,7698,7782,7788')-LENGTH(REPLACE('7654,7698,7782,7788',',',''))+1
此處利用 mysql 庫的 help_topic 表的 help_topic_id 來作為變量,因為 help_topic_id 是自增的,當然也可以用其他表的自增字段輔助。
help_topic 表:
註意,這個輔助表的ID最大長度隻有658;如果過長的字符串,可能需要借助其他自增的輔助表(可以是現有表,也可以自己造一個 1,2,3,4 遞增的行即可)
【4.2】正式的原理解析
原SQL
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('7654,7698,7782,7788',',',help_topic_id+1),',',-1) AS num FROM mysql.help_topic WHERE help_topic_id < LENGTH('7654,7698,7782,7788')-LENGTH(REPLACE('7654,7698,7782,7788',',',''))+1
Step1:首先獲取最後需被拆分成多少個字符串,利用 help_topic_id 來模擬遍歷 第n個字符串。
這一步核心就是獲取,有多少個分隔符,比如本文的案例,就是知道有多少個逗號
涉及的代碼片段:
help_topic_id < LENGTH('7654,7698,7782,7788')-LENGTH(REPLACE('7654,7698,7782,7788',',',''))+1
因為 help_topic_id是從0開始的,所以會得出 help_topic_id 值為:0~3,共4行數據;
Step2:根據“,”逗號來拆分字符串,此處利用 SUBSTRING_INDEX(str, delim, count) 函數,最後把結果賦值給 num 字段。
涉及的代碼片段:
SUBSTRING_INDEX(SUBSTRING_INDEX('7654,7698,7782,7788',',',help_topic_id+1),',',-1) AS num
第一步:
以”,”逗號為分隔符,根據 help_topic_id 的值來截取第n+1個分隔符之前所有的字符串。 (此處 n+1 是因為help_topic_id 是從0開始算起,而此處需從第1個分隔符開始獲取。)
SUBSTRING_INDEX('7654,7698,7782,7788',',',help_topic_id+1) eg: 當 help_topic_id = 0時,獲取到的字符串 = 7654 當 help_topic_id = 1時,獲取到的字符串 = 7654,7698 …(以此類推)
第二步:
以”,”逗號為分隔符,截取倒數第1個分隔符之後的所有字符串。
SUBSTRING_INDEX(SUBSTRING_INDEX('7654,7698,7782,7788',',',help_topic_id+1),',',-1) eg: 根據第一步,當 help_topic_id = 0時,獲取到的字符串 = 7654,此時第二步截取的字符串 = 7654 根據第一步,當 help_topic_id = 1時,獲取到的字符串 = 7654,7698,此時第二步截取的字符串 = 7698 …(以此類推)
最終成功實現瞭以下效果 ~
擴展:判斷外部值是否在 num列值中
【5.1】find_in_set
如果匹配到瞭會得出1;如下圖
實際業務中,我們隻需要 where find_in_set(id,ids)>0
就可以判斷出;id列,是否在 ids列中出現過;做表連接的時候,也可以這樣;
【5.2】instr
我們可以看出,instr是找出 參數2=》也就是上圖中的 ‘123’ 在參數1=》也就是上圖中的 ‘321,123,555,12345’ 中最開始出現的位置;
所以我們也隻需要 where find_in_set(ids,id)>0 ,就可以判斷出 id 在 ids中出現過;
但這有一個問題,如果逗號分隔開的字符串,包含我們查找的字符串,也會顯示出來,這就不符合我們 根據分隔符 , 判斷 查找字符串id 是否出現在 ids 中;
如下:
我們本來想查以逗號為分隔的完全匹配,但是12345包含瞭 123 所以查出來的結果也是>0的,這不對;
所以我們為瞭避免這種情況,可以加上分隔符;然後再用 字符串+分隔符作為 查找的字符串 來 匹配;
我們被查找的字符串 ids 中 再加上一個正常的 123, 再查看,如下圖:確實是對的
文章參考
https://blog.csdn.net/pjymyself/article/details/81668157
https://www.cnblogs.com/gered/p/10797012.html#_label1
到此這篇關於MySql字符串拆分實現split功能(字段分割轉列)的文章就介紹到這瞭,更多相關MySql字符串拆分內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- MySQL查詢字段實現字符串分割split功能的示例代碼
- MySQL 十大常用字符串函數詳解
- MySQL 字符串拆分操作(含分隔符的字符串截取)
- mysql根據逗號將一行數據拆分成多行數據
- MySQL 字符串拆分實例(無分隔符的字符串截取)