SQL之行转列

 

例题:如何将逗号分隔的一行数据变成多行

例如表格如下:

SQL之行转列

 

需要转换的结果如下:

SQL之行转列

 

 

 

转换的SQL语句如下:

select substring_index(substring_index(a.userIds,,,b.help_topic_id+1),,,-1) as id,
substring_index(substring_index(a.userNames,,,b.help_topic_id+1),,,-1) username 
from test_actor a 
join mysql.help_topic b 
on b.help_topic_id < (length(a.userNames) - length(replace(a.userNames,,,‘‘))+1) 
and b.help_topic_id < (length(a.userIds) - length(replace(a.userIds,,,‘‘))+1);

 

知识点如下:

1.substring_index函数

 

substring_index(str,delim,count)

 

      str:要处理的字符串

 

      delim:分隔符

 

      count:计数

例子:str=www.wikibt.com

substring_index(str,‘.‘,1)

结果是:www

substring_index(str,‘.‘,2)

结果是:www.wikibt

也就是说,如果count是正数,那么就是从左往右数,第N个分隔符的左边的全部内容

相反,如果是负数,那么就是从右边开始数,第N个分隔符右边的所有内容,如:

substring_index(str,‘.‘,-2)

结果为:wikibt.com

有人会问,如果我要中间的的wikibt怎么办?

很简单的,两个方向:

从右数第二个分隔符的右边全部,再从左数的第一个分隔符的左边:

substring_index(substring_index(str,‘.‘,-2),‘.‘,1);

 

2.help_topic这张表是mysql自带的连续数列的表

mysql.help_topic这张表我们只用到了它的help_topic_id,可以看到这个help_topic_id是从0开始一直连续的,join这张表只是为了确定数据行数。现在假设我的mysql.help_topic一共只有5条数据,那么最多可转成5行数据,若果现在主演的名字有6个就不能用mysql.help_topic这张表了。

SQL之行转列

由此看出我们完全可以找其他表来替代mysql.help_topic,只要满足表的id是连续的,且数据条数超过了你要转换的行数即可。

 

3.substring_index(substring_index(a.userNames,‘,‘,b.help_topic_id+1),‘,‘,-1) 理解如下

SQL之行转列

 

 

 

4.on条件后面的b.help_topic_id < (length(a.userNames) - length(replace(a.userNames,‘,‘,‘‘))+1) 理解如下:

 

 是得到被逗号分隔的字段一共有几个(既计算出原始的字段长度,和去掉逗号的字段长度,两者的差就是有几个逗号,三个逗号就表示有四个字段...)

 

为什么后面还有一个加1?

 

3+1=4,可以这样理解,一根绳子剪三刀可以分成四段,同理一个主演名字串,三个逗号可以分隔出四个主演的名字。

 

既然是将一个字段按照逗号分隔转成多行,那么现在已经确定了行数。

 

5.join 这个join最基本原理是笛卡尔积。通过这个方式来实现循环

这种方法的缺点在于,我们需要一个拥有连续数列的独立表(这里是incre_table)。并且连续数列的最大值一定要大于符合分割的值的个数。

例如有一行的mSize 有100个逗号分割的值,那么我们的incre_table 就需要有至少100个连续行。

mysql内部也有现成的连续数列表可用。如mysql.help_topic: help_topic_id 共有504个数值,一般能满足于大部分需求了。

SQL之行转列

上一篇:Django+MySQL开发记录


下一篇:ADO 链接数据库获取结果集 SQLServer Oracle