mysql 列轉行的技巧 分享

2022-09-25 20:45:09 字數 1899 閱讀 6194

前言:

由於很多業務表因為歷史原因或者效能原因,都使用了違反第一正規化的設計模式。即同乙個列中儲存了多個屬性值(具體結構見下表)。

這種模式下,應用常常需要將這個列依據分隔符進行分割,並得到列轉行的結果。

表資料:

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...