1. 程式人生 > 其它 >SQL之行轉列

SQL之行轉列

例題:如何將逗號分隔的一行資料變成多行

例如表格如下:

需要轉換的結果如下:

轉換的SQL語句如下:

select substring_index(substring_index(a.userIds,',',b.help_topic_id+1),',',-1) as id,
substring_index(substring_index(a.userNames,',',b.help_topic_id+1),',',-1) username 
from test_actor a 
join mysql.help_topic b 
on b.help_topic_id < (length(a.userNames) -
length(replace(a.userNames,',',''))+1) and b.help_topic_id < (length(a.userIds) - length(replace(a.userIds,',',''))+1);

知識點如下:

1.substring_index函式

substring_index(str,delim,count)

str:要處理的字串

delim:分隔符

count:計數

例子:str=www.wikibt.com

substring_index(str,'.',1)

結果是:www

substring_index(str,'.',2)

結果是:www.wikibt

也就是說,如果count是正數,那麼就是從左往右數,第N個分隔符的左邊的全部內容

相反,如果是負數,那麼就是從右邊開始數,第N個分隔符右邊的所有內容,如:

substring_index(str,'.',-2)

結果為:wikibt.com

有人會問,如果我要中間的的wikibt怎麼辦?

很簡單的,兩個方向:

從右數第二個分隔符的右邊全部,再從左數的第一個分隔符的左邊:

substring_index(substring_index(str,'.',-2),'.',1);

2.help_topic這張表是mysql自帶的連續數列的表

mysql.help_topic這張表我們只用到了它的help_topic_id,可以看到這個help_topic_id是從0開始一直連續的,join這張表只是為了確定資料行數。現在假設我的mysql.help_topic一共只有5條資料,那麼最多可轉成5行資料,若果現在主演的名字有6個就不能用mysql.help_topic這張表了。

由此看出我們完全可以找其他表來替代mysql.help_topic,只要滿足表的id是連續的,且資料條數超過了你要轉換的行數即可。

3.substring_index(substring_index(a.userNames,',',b.help_topic_id+1),',',-1) 理解如下

4.on條件後面的b.help_topic_id < (length(a.userNames) - length(replace(a.userNames,',',''))+1) 理解如下:

是得到被逗號分隔的欄位一共有幾個(既計算出原始的欄位長度,和去掉逗號的欄位長度,兩者的差就是有幾個逗號,三個逗號就表示有四個欄位...)

為什麼後面還有一個加1?

3+1=4,可以這樣理解,一根繩子剪三刀可以分成四段,同理一個主演名字串,三個逗號可以分隔出四個主演的名字。

既然是將一個欄位按照逗號分隔轉成多行,那麼現在已經確定了行數。

5.join這個join最基本原理是笛卡爾積。通過這個方式來實現迴圈

這種方法的缺點在於,我們需要一個擁有連續數列的獨立表(這裡是incre_table)。並且連續數列的最大值一定要大於符合分割的值的個數。

例如有一行的mSize 有100個逗號分割的值,那麼我們的incre_table 就需要有至少100個連續行。

mysql內部也有現成的連續數列表可用。如mysql.help_topic: help_topic_id 共有504個數值,一般能滿足於大部分需求了。