有如下一个表,需要将tag列的每个标签都提取出来,一行对应一个标签
mysql> select * from user_tag;
+--------+-----------------+
| userid | tag |
+--------+-----------------+
| 1 | css,go |
| 2 | mysql,sql,html |
| 3 | css,spring,php |
| 4 | css,java,go,sql |
| 5 | java,c |
| 6 | c |
+--------+-----------------+
6 rows in set (0.00 sec)
行转列实现过程
1.首先我们算出每个用户的标签个数:
select userid,LENGTH(a.tag)-LENGTH(REPLACE(a.tag,',',''))+1 from user_tag;
mysql> select userid,tag,LENGTH(tag)-LENGTH(REPLACE(tag,',',''))+1 from user_tag;
+--------+-----------------+-------------------------------------------+
| userid | tag | LENGTH(tag)-LENGTH(REPLACE(tag,',',''))+1 |
+--------+-----------------+-------------------------------------------+
| 1 | css,go | 2 |
| 2 | mysql,sql,html | 3 |
| 3 | css,spring,php | 3 |
| 4 | css,java,go,sql | 4 |
| 5 | java,c | 2 |
| 6 | c | 1 |
+--------+-----------------+-------------------------------------------+
6 rows in set (0.00 sec)
2.我们用substring_index来切分每个用户的标签,第一步骤中得到了每个用户的标签个数,也就得到了tag切分的次数,然后我们利用另一个序列表来构造一个切分视图
mysql> SELECT a.*,LENGTH(a.tag)-LENGTH(REPLACE(a.tag,',',''))+1,b.help_topic_id
-> from user_tag a left join mysql.help_topic b
-> on b.help_topic_id < (LENGTH(a.tag)-LENGTH(REPLACE(a.tag,',',''))+1);
+--------+-----------------+-----------------------------------------------+---------------+
| userid | tag | LENGTH(a.tag)-LENGTH(REPLACE(a.tag,',',''))+1 | help_topic_id |
+--------+-----------------+-----------------------------------------------+---------------+
| 1 | css,go | 2 | 0 |
| 1 | css,go | 2 | 1 |
| 2 | mysql,sql,html | 3 | 0 |
| 2 | mysql,sql,html | 3 | 1 |
| 2 | mysql,sql,html | 3 | 2 |
| 3 | css,spring,php | 3 | 0 |
| 3 | css,spring,php | 3 | 1 |
| 3 | css,spring,php | 3 | 2 |
| 4 | css,java,go,sql | 4 | 0 |
| 4 | css,java,go,sql | 4 | 1 |
| 4 | css,java,go,sql | 4 | 2 |
| 4 | css,java,go,sql | 4 | 3 |
| 5 | java,c | 2 | 0 |
| 5 | java,c | 2 | 1 |
| 6 | c | 1 | 0 |
+--------+-----------------+-----------------------------------------------+---------------+
15 rows in set (0.00 sec)
以上结果的help_topic_id列,即是tag的切分位置
3.根据help_topic_id进行切分
3.1根据help_topic_id切分分别得到第一个逗号,第二个逗号…之前的tag
mysql> SELECT a.userid,SUBSTRING_INDEX(a.tag,',',b.help_topic_id+1) as tag
-> from user_tag a left join mysql.help_topic b
-> on b.help_topic_id < (LENGTH(a.tag)-LENGTH(REPLACE(a.tag,',',''))+1);
+--------+-----------------+
| userid | tag |
+--------+-----------------+
| 1 | css |
| 1 | css,go |
| 2 | mysql |
| 2 | mysql,sql |
| 2 | mysql,sql,html |
| 3 | css |
| 3 | css,spring |
| 3 | css,spring,php |
| 4 | css |
| 4 | css,java |
| 4 | css,java,go |
| 4 | css,java,go,sql |
| 5 | java |
| 5 | java,c |
| 6 | c |
+--------+-----------------+
15 rows in set (0.01 sec)
3.2对上述切分后的tag再处理一次,取最后一个逗号后面的字符串
mysql> SELECT a.userid,SUBSTRING_INDEX(SUBSTRING_INDEX(a.tag,',',b.help_topic_id+1),',',-1) as tag
-> from user_tag a left join mysql.help_topic b
-> on b.help_topic_id < (LENGTH(a.tag)-LENGTH(REPLACE(a.tag,',',''))+1);
+--------+--------+
| userid | tag |
+--------+--------+
| 1 | css |
| 1 | go |
| 2 | mysql |
| 2 | sql |
| 2 | html |
| 3 | css |
| 3 | spring |
| 3 | php |
| 4 | css |
| 4 | java |
| 4 | go |
| 4 | sql |
| 5 | java |
| 5 | c |
| 6 | c |
+--------+--------+
15 rows in set (0.01 sec)
这种列转行的方法有一些前提条件:
1.分割符需要统一;
2.序列表mysql.help_topic提供的序列help_topic_id需要大于每个用户的标签数。
来源:CSDN
作者:灯火觅阑珊
链接:https://blog.csdn.net/weixin_39004901/article/details/90257881