MySQL
每周練習答案
這里和大家分享下本周練習題的一種解題思路
將題目簡化一下,其實就是實現(xiàn)這樣一個功能:
我們將使用逗號分隔的數(shù)據(jù),拆分為多行數(shù)據(jù),熟悉MySQL的同學,可能會想到,這有點兒像group_concat函數(shù),但這是他的逆過程
測試數(shù)據(jù)
create table tm_company(
company_name varchar(10),
company_industry varchar(20)
);
insert into tm_company(company_name,company_industry) values('A公司','移動互聯(lián)網(wǎng),金融');
insert into tm_company(company_name,company_industry) values('B公司','移動互聯(lián)網(wǎng)');
insert into tm_company(company_name,company_industry) values('C公司','教育,招聘,魔法');
select *from tm_company;
解決方案
我們先來思考這樣一個問題,怎樣才能把用逗號分隔的數(shù)據(jù)拆分呢?
這里需要了解MySQL的字符串函數(shù)
https://dev.mysql.com/doc/refman/5.7/en/string-functions.html
SUBSTRING_INDEX
找一下,會發(fā)現(xiàn)這個函數(shù),挺符合我們需求的
SUBSTRING_INDEX(str,delim,count)
str 就是我們要分隔的字符串
delim 就是我們的分隔符
當count為正數(shù)時,我們從左側開始截取,截止到delim第count次出現(xiàn)時;當count為負數(shù)時,則從右側開始
mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);
-> 'www.mysql'
mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);
-> 'mysql.com'
我們來試一下
select
company_name,
substring_index(company_industry,',',1),
substring_index(company_industry,',',2),
substring_index(company_industry,',',-1)
from
tm_company;
看上去,好像接近我們想要的數(shù)據(jù),但還是有些問題
比如,我們需要判斷到底要分隔幾次,那該怎樣判斷要分隔幾次呢?
其實就是看有幾個逗號,那怎樣判斷有幾個逗號呢?
好像并沒有判斷字符出現(xiàn)次數(shù)的函數(shù),但我們可以繞個彎來實現(xiàn)
像這樣,我們把逗號都替換掉,看數(shù)據(jù)長度減少了多少,就可以了
select
company_name,
company_industry,
length(company_industry)-length(replace(company_industry,',',''))
from
tm_company;
我們再來觀察下這個數(shù)據(jù)
- 1個逗號的時候,我們需要拆分2次
- 0個逗號的時候,我們需要拆分1次
- 2個逗號的時候,我們需要拆分3次
我們以C公司的數(shù)據(jù)來測試下
select
substring_index('教育,招聘,魔法',',',1),
substring_index('教育,招聘,魔法',',',2),
substring_index('教育,招聘,魔法',',',3)
我們觀察下,會發(fā)現(xiàn),最右邊的數(shù)據(jù)就是我們想要的
select
substring_index(substring_index('教育,招聘,魔法',',',1),',',-1),
substring_index(substring_index('教育,招聘,魔法',',',2),',',-1),
substring_index(substring_index('教育,招聘,魔法',',',3),',',-1)
哎,好像是了嘛,數(shù)據(jù)現(xiàn)在已經(jīng)分隔好了,現(xiàn)在的問題,好像變成了列轉行
列轉行
因為我們的數(shù)據(jù)是動態(tài)分隔的,所以,做列轉行的話,不能用之前的方法,可能需要使用另一種方法
我們看下上面分隔的時候,使用的下標,是自增的,而且和逗號的數(shù)量也有關
暢想一下(估計是經(jīng)驗),可以這樣來做
select *from (
select 0 as id
union select 1
union select 2
union select 3
union select 4
) base
我們可以這個數(shù)據(jù)來表示逗號的數(shù)量,然后這樣
select
a.company_name,
a.company_industry,
substring_index(substring_index(a.company_industry,',',b.id+1),',',-1)
from
tm_company a
join (
select 0 as id
union select 1
union select 2
union select 3
union select 4
) b on b.id <= length(a.company_industry)-length(replace(a.company_industry,',',''))
order by
a.company_name;
好了,完成,我們通過1對多的關系,進行了列轉行,再配合substring_index函數(shù),我們就完成了上面的問題。
先這樣,大家先理解下,歡迎反饋。