下面小編就為大家帶來一篇mysql 列轉行的技巧(分享)。小編覺得蠻不錯的,現在就分享給大家,也給大家做個參考。一起跟著小編過來看看吧
前言:
#由於很多業務表因為歷史原因或效能原因,都使用了違反第一範式的設計模式。即同一個列中儲存了多個屬性值(具體結構見下表)。
這種模式下,應用程式常常需要將這個列依據分隔符號分割,並且得到列轉行的結果。
表格資料:
ID | Value |
## 1 | |
2 | |
##3 | tiny,big |
期望得到結果:
#ID | 值 |
#1 | 微小 |
1 | 小 |
1 | 大 |
2 | #小 |
2 | 中 |
#3 | 微小 | ##
3 | big |
#正文:
#需要处理的表 create table tbl_name (ID int ,mSize varchar(100)); insert into tbl_name values (1,'tiny,small,big'); insert into tbl_name values (2,'small,medium'); insert into tbl_name values (3,'tiny,big'); #用于循环的自增表 create table incre_table (AutoIncreID int); insert into incre_table values (1); insert into incre_table values (2); insert into incre_table values (3);
select a.ID,substring_index(substring_index(a.mSize,',',b.AutoIncreID),',',-1) from tbl_name a join incre_table b on b.AutoIncreID <= (length(a.mSize) - length(replace(a.mSize,',',''))+1) order by a.ID;
原理分析:
這個join最基本原理就是笛卡兒積。透過這個方式來實現循環。
以下是具體問題分析:
length(a.Size) - length(replace(a.mSize,',',' '))+1 表示了,依照逗號分割後,改列擁有的數值數量,以下簡稱n
join過程的偽代碼:
根據ID進行循環
{ 判断:i 是否 <= n {
取得最靠近第i 個逗號之前的數據, 即substring_index(substring_index(a.mSize,',',b.ID),',',-1)
i = i +1 } ID = ID +1 }
總結:
這種方法的缺點在於,我們需要一個擁有連續數列的獨立表(這裡是incre_table)。且連續數列的最大值一定大於符合分割的值的個數。
例如有一行的mSize 有100個逗號分割的值,那麼我們的incre_table 就需要有至少100個連續行。
當然,mysql內部也有現成的連續數列表可用。如mysql.help_topic: help_topic_id 共有504個數值,一般能滿足於大部分需求了。
改寫後如下:
select a.ID,substring_index(substring_index(a.mSize,',',b.help_topic_id+1),',',-1) from tbl_name a join mysql.help_topic b on b.help_topic_id < (length(a.mSize) - length(replace(a.mSize,',',''))+1) order by a.ID;
以上是mysql列轉行的技巧實例分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!