按照指定字符进行合并或拆分是经常碰到的场景,MySQL在合并的写法上比较简单,但是按指定字符拆分相对比较麻烦一点(也就是要多写一些字符)。本文将举例演示如何进行按照指定字符合并及拆分。

MySQL数据库中按照指定字符合并可以直接用group_concat来实现。

  1. mysql> create table tb_group(id int auto_increment primary key ,col1 varchar(20));
  2. Query OK, 0 rows affected (0.01 sec)
  1. mysql> insert into tb_group(col1) values(\'a\'),(\'c\'),(\'dddd\'),(\'ewdw\'),(\'vxgdh\');;
  2. Query OK, 5 rows affected (0.01 sec)
  3. Records: 5 Duplicates: 0 Warnings: 0

默认是按照逗号进行合并的,例如:

  1. mysql> select group_concat(col1) from tb_group;
  2. +---------------------+
  3. | group_concat(col1) |
  4. +---------------------+
  5. | a,c,dddd,ewdw,vxgdh |
  6. +---------------------+
  7. 1 row in set (0.01 sec)

指定分隔符合并,例如指定使用 ||  符号进行合并

  1. mysql> select group_concat(col1,\'||\') from tb_group;
  2. +-------------------------------+
  3. | group_concat(col1,\'||\') |
  4. +-------------------------------+
  5. | a||,c||,dddd||,ewdw||,vxgdh|| |
  6. +-------------------------------+
  7. 1 row in set (0.00 sec)

默认情况下,合并后的长度不能超过1024,否则结果会被截断

例如,我再写个脚本插入一些数据

  1. # 使用shell脚本来实现
  2. vim test_insert.sh
  3. # 添加如下内容
  4. #!/bin/bash
  5. # gjc
  6. for i in {1..1025}
  7. do
  8. mysql -uroot -p\'123456\' --socket=/data/mysql3306/tmp/mysql.sock -e "insert into testdb.tb_group1(col1)values(\'a\') "
  9. done
  10. # 运行脚本插入数据
    sh test_insert.sh
  1. mysql> select count(*)from tb_group;
  2. +----------+
  3. | count(*) |
  4. +----------+
  5. | 1030 |
  6. +----------+
  7. 1 row in set (0.00 sec)

再进行合并

  1. mysql> select group_concat(col1)cols, length(group_concat(col1)) col_len from tb_group\G
  2. *************************** 1. row ***************************
  3. cols: a,c,dddd,ewdw,vxgdh,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,
  4. col_len: 1024
  5. 1 row in set, 2 warnings (0.01 sec)

可以看出,结果中总长度字节只有1024

对于这种情况,实际使用时肯定是不满足的,如何解决呢?其实此长度与MySQL数据库的group_concat_max_len参数有直接关系(默认为1024)

  1. mysql> show global variables like \'group_concat_max_len\';
  2. +----------------------+-------+
  3. | Variable_name | Value |
  4. +----------------------+-------+
  5. | group_concat_max_len | 1024 |
  6. +----------------------+-------+
  7. 1 row in set (0.08 sec)

那我们调整一下参数看看

  1. /* 修改全局参数,这样所有的新连接都会生效 */
  2. mysql> set global group_concat_max_len=102400;
  3. Query OK, 0 rows affected (0.01 sec)
  4. /* 修改本会话参数,这样当前连接不用退出也可以生效 */
  5. mysql> set session group_concat_max_len=102400;
  6. Query OK, 0 rows affected (0.00 sec)
  7. mysql> show global variables like \'group_concat_max_len\';
  8. +----------------------+--------+
  9. | Variable_name | Value |
  10. +----------------------+--------+
  11. | group_concat_max_len | 102400 |
  12. +----------------------+--------+
  13. 1 row in set (0.00 sec)
  14. mysql> show variables like \'group_concat_max_len\';
  15. +----------------------+--------+
  16. | Variable_name | Value |
  17. +----------------------+--------+
  18. | group_concat_max_len | 102400 |
  19. +----------------------+--------+
  20. 1 row in set (0.01 sec)

再合并一下看看

  1. mysql> select group_concat(col1)cols, length(group_concat(col1)) col_len from tb_group\G
  2. *************************** 1. row ***************************
  3. cols: a,c,dddd,ewdw,vxgdh,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
  4. col_len: 2069
  5. 1 row in set (0.01 sec)

这样结果就对了。因此生产环境中 该参数建议调整为合适的大小。

(Tips:Oracle数据库中可以使用listagg或wm_concat等多种方式实现,也比较简单,可以自行测试)

按指定字符拆分字符串,也是比较常见的场景。但是MySQL数据库中字符串的拆分没有其他数据库那么方便(其他数据库直接有拆分函数),且需要借助mysql库中的mysql.help_topic表来辅助实现。例子如下:

  1. mysql> create table tb_split(id int primary key auto_increment,col1 varchar(20));
  2. Query OK, 0 rows affected (0.01 sec)
  3. mysql> insert into tb_split(col1) values(\'a,b,c,d\'),(\'c,a,g,h\');
  4. Query OK, 2 rows affected (0.01 sec)
  5. Records: 2 Duplicates: 0 Warnings: 0
  1. mysql> SELECT a.id, substring_index(substring_index(a.col1, \',\', b.help_topic_id + 1), \',\',- 1) NAME

    FROM tb_split a JOIN mysql.help_topic b

    ON b.help_topic_id < (length(a.col1) - length(REPLACE(a.col1, \',\', \'\')) + 1);
  2. +----+------+
  3. | id | NAME |
  4. +----+------+
  5. | 1 | a |
  6. | 1 | b |
  7. | 1 | c |
  8. | 1 | d |
  9. | 2 | c |
  10. | 2 | a |
  11. | 2 | g |
  12. | 2 | h |
  13. +----+------+
  14. 8 rows in set (0.00 sec)

这样也就实现了拆分。

如果是其他分隔符的,修改瑞阳的分隔符字段即可。

  1. mysql> insert into tb_split(col1) values(\'a|v|f\');
  2. Query OK, 1 row affected (0.00 sec)
  3. mysql> select * from tb_split;
  4. +----+---------+
  5. | id | col1 |
  6. +----+---------+
  7. | 1 | a,b,c,d |
  8. | 2 | c,a,g,h |
  9. | 3 | a|v|f |
  10. +----+---------+
  11. 3 rows in set (0.01 sec)
  12. mysql> SELECT a.id, substring_index(substring_index(a.col1, \'|\', b.help_topic_id + 1), \'|\',- 1) col_split FROM tb_split a JOIN mysql.help_topic b ON b.help_topic_id < (length(a.col1) - length(REPLACE(a.col1, \'|\', \'\')) + 1) where a.id=3;
  13. +----+-----------+
  14. | id | col_split |
  15. +----+-----------+
  16. | 3 | a |
  17. | 3 | v |
  18. | 3 | f |
  19. +----+-----------+
  20. 3 rows in set (0.00 sec)

这样就完成按照指定字符的合并及拆分了。

本文介绍了MySQL常用的合并及拆分方法,对于擅长写SQL的同学也可以使用其他方式实现,以便解决权限不足(例如拆分时需要使用mysql库的help_topic表的权限)等情况下的需求。

想了解更多内容或参与技术交流可以关注微信公众号【数据库干货铺】或进技术交流群沟通。

 

版权声明:本文为gjc592原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/gjc592/p/13191101.html