前言:
由於很多業務表因為歷史原因或者效能原因,都使用了違反第一正規化的設計模式。即同乙個列中儲存了多個屬性值(具體結構見下表)。
這種模式下,應用常常需要將這個列依據分隔符進行分割,並得到列轉行的結果。
表資料:
idvalue
1tiny,small,big
2small,medium
3tiny,big
期望得到結果:
idvalue
1tiny
1small
1big
2small
2medium
3tiny
3big
正文:#需要處理的表
create table tbl_name (id int ,msize varchar(100));
insert into tbl_nam程式設計客棧e values (1,'tiny,small,big');
insert into tbl_name values (2,'small,');
insert into tbl_name values (3,'tiny,big');
#用於迴圈的自增表
cr 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),',',
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 列轉行的技巧(分享)
本文位址:
Mysql 列轉行 例項
箱表 create table yoshop shang activity box id int 11 not null auto increment comment 編號 activity id int 11 not null comment 活動id number int 11 not null...
Mysql 採用列轉行
欄位的拆分 使用函式substring index str,delim,count str 拆分物件 delim 拆分標識 substring index 搜尋時執行區分大小寫的匹配 delim count 拆分方式 如果 count為正,則返回最終分隔符左側的所有內容 從左側開始計算 如果coun...
MySQL中的列轉行方法
資料如下 create table test id int 10 not null auto increment primary key,name varchar 20 default null,course varchar 20 default null,score float default 0...