Row and column conversion skills of MySQL comma-separated fields

Foreword:

Because many business tables use design patterns that violate the first normal form for historical reasons or performance reasons. That is, multiple attribute values ​​are stored in the same column (see the following table for the specific structure).

In this mode, the application often needs to divide the column according to the delimiter, and get the result of column-to-row.

Table data:

ID  Value
1 tiny,small,big
2 small,medium
3 tiny,big

Expected result:

ID Value
1 tiny
1 small
1 big
2 small
2 medium
3 tiny
3 big

text:

copy code

#The table to be processed
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');

#Auto-increment table for loop
create table incre_table (AutoIncreID int);
insert into incre_table values (1);
insert into incre_table values (2);
insert into incre_table values (3);

copy code

 

copy code

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;

copy code

 

Principle analysis:

The most basic principle of this join is the Cartesian product. In this way, the cycle is realized.

The following is an analysis of specific problems:

length(a.Size) - length(replace(a.mSize,',',''))+1 indicates that after dividing by commas, the number of values ​​in the column is changed, hereinafter referred to as n

Pseudo code for join process:

Loop by ID

{

Judgment: whether i <= n

{

Get the data closest to the ith comma, i.e. substring_index(substring_index(a.mSize,',',b.ID),',',-1)

i = i +1 

}

ID = ID +1 

}

 

Summarize:

The downside of this approach is that we need a separate table (incre_table in this case) with consecutive columns. And the maximum value of the continuous sequence must be greater than the number of values ​​that meet the division.

For example, there is a row of mSize with 100 comma-separated values, then our incre_table needs to have at least 100 consecutive rows.

Of course, there is also a ready-made list of consecutive numbers available inside mysql. For example, mysql.help_topic: help_topic_id has a total of 504 values, which can generally meet most needs.

Rewritten as follows:

copy code

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;

copy code

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324788502&siteId=291194637