1. 程式人生 > >【mysql】逗號分割字段的行列轉換

【mysql】逗號分割字段的行列轉換

lec mysql 由於 int creat prim sql語句 post 之前

  由於很多業務表因為歷史原因或者性能原因,都使用了違反第一範式的設計模式,即同一個列中存儲了多個屬性值。這種模式下,應用常常需要將這個列依據分隔符進行分割,並得到列轉行的結果:

建表語句:

 1 DROP table if EXISTS tbl_name;
 2 CREATE TABLE tbl_name(
 3     id       int(11)    not null auto_increment,
 4     userName varchar(100)    not null,
 5 PRIMARY KEY(id)
 6 )
 7 ENGINE=InnoDB AUTO_INCREMENT=
2 DEFAULT CHARSET=utf8; 8 9 insert into tbl_name values (1,a,aa,aaa); 10 insert into tbl_name values (2,b,bb); 11 insert into tbl_name values (3,c,cc);

如下圖:

技術分享圖片

sql語句:

1 SELECT a.id,SUBSTRING_INDEX(SUBSTRING_INDEX(a.userName,,,b.help_topic_id+1),,,-1) as name  
2 from tbl_name a left join
mysql.help_topic b 3 on b.help_topic_id < (LENGTH(a.userName)-LENGTH(REPLACE(a.userName,,,‘‘))+1) 4 ORDER BY a.id;

執行結果:

技術分享圖片

分析如下:

LENGTH(a.userName)-LENGTH(REPLACE(a.userName,,,‘‘))+1

表示了按逗號分割後,獲得行轉成列的數量,以下簡稱n;

根據id進行循環

{
  判斷:i 是否 <= n
    {
      獲取最靠近第 i 個逗號之前的數據, 即 SUBSTRING_INDEX(SUBSTRING_INDEX(a.userName,
,,b.help_topic_id+1),,,-1)       i = i +1     }   id = id +1 }

總結:

這種方法的缺點在於,我們需要一個擁有連續數列的獨立表(這裏是incre_table)。並且連續數列的最大值一定要大於符合分割的值的個數。當然,mysql內部也有現成的連續數列表可用。如mysql.help_topic: help_topic_id 共有504個數值,一般能滿足於大部分需求了。

【mysql】逗號分割字段的行列轉換