此篇写单行转多列的方法。 其中用到的函数有replace(),length(),char_length(),substring(),substring_index(),concat()。首先会介绍各个函数的用法,之后会贴出单行转多列的语句。
应用场景是一个学生表,在班级字段中保存了该名学生上过的班级,并用“;”号分隔,要转换成一行是一个班级的格式。同样适用于一个字段中保存多个手机号。
replace('a','b','c');从字符串a中搜索字符串b,并用字符串c代替。
length(a);获取a对应字段的字节长度。
char_length(a);获取a的字符串长度。
个人理解就是char_length()得到的是看到的字符串的长度,而length()字节则是编码转化的长度,例如一个UTF-8的汉字是3个字节,是一个字符。
concat('a','b','c');将字符串a,b,c连接起来。
substring('a',b,c);在字符串a中从位置b开始,截去长度为c的字符串。b,c都是整数。b要求大于等于1。
substring_index('a','b',c);展示在字符串a中,第c次出现字符串b之前的字符串。a,b都是字符串,c是整数。
具体转换学生表
新建一个tb_sequence表,用来和student表cross join 获得笛卡尔乘积,先得到多列。表中只有一个ID,是自动递增的INT。
tb_sequence
首先用corss join 获得多列,这里要记得给 cross join 后的查询结果集一个别名,不然报错。
之后运用之前介绍的函数从className中截取出需要的字符串。这个过程是相当眼晕的,写完需要一瓶眼药水。这里主要利用了要处理的字符串格式统一的特点,都是4个字符串长度,像手机号码之类的可以类似处理,如果是不规则的还要自己再探索下。
select name,
substring(replace(className,';',''),char_length(replace(substring_index(className,';',a.id -1),';',''))+1,4) as className
from tb_sequence a cross join (
select id, name,className,length(className)-length(replace(className,';','')) as size from student b
)b
on a.id<=b.size order by b.id;
热门评论
给代码,求实验环境*-*