MySQL 固定分隔符列转行

人走茶凉 提交于 2019-12-06 01:59:30

有如下一个表,需要将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需要大于每个用户的标签数。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!