当前位置: 代码网 > it编程>数据库>Mysql > MySQL concat_ws和group_concat函数有什么区别?一文搞懂

MySQL concat_ws和group_concat函数有什么区别?一文搞懂

2026年07月25日 Mysql 我要评论
一、concat() 函数1、功能:将多个字符串连接成一个字符串。2、语法:concat(str1, str2,…)返回结果为连接参数产生的字符串,如果有任何一个参数为 null,则返回

一、concat() 函数

1、功能:将多个字符串连接成一个字符串。

2、语法:concat(str1, str2,…)

返回结果为连接参数产生的字符串,如果有任何一个参数为 null,则返回值为 null。

举例1

select concat(id,name,email) as userinfo from users;

上面有一行为 null 是因为 users 表中有一行的 email 值为 null。

举例2

在例1的结果中三个字段 id,name,email 的组合没有分隔符,我们可以加一个逗号作为分隔符。

select concat(id,',',name,',',email) as userinfo from users;

二、concat_ws() 函数

1、功能:和 concat() 一样,将多个字符串连接成一个字符串,但是可以一次性指定分隔符~(concat_ws 就是 concat with separator)

2、语法:concat_ws(separator, str1, str2, …)

说明:第一个参数指定分隔符。需要注意的是分隔符不能为 null,如果为 null,则返回结果为 null。

举例

使用 concat_ws() 将 分隔符指定为逗号。

select concat_ws(',',id,name,email) as userinfo from users;

把分隔符指定为 null,结果全部变成了 null。

三、group_concat() 函数

前言:

在有 group by 的查询语句中,select 指定的字段要么就包含在 group by 语句的后面,作为分组的依据,要么就包含在聚合函数中。

举例1

该例查询了name 相同的的人中最小的 id。如果我们要查询 name 相同的人的所有的id呢?

当然我们可以这样查询:

但是这样同一个名字出现多次,看上去非常不直观。

有没有更直观的方法,既让每个名字都只出现一次,又能够显示所有的名字相同的人的 id呢? ——使用 group_concat()

1、功能:将 group by 产生的同一个分组中的值连接起来,返回一个字符串结果。

2、语法:

group_concat([distinct] 要连接的字段 
			 [order by asc/desc 排序字段] 
			 [separator '分隔符'])

说明:

通过使用 distinct 可以排除重复值;

如果希望对结果中的值进行排序,可以使用 order by 子句;separator 是一个字符串值,缺省为一个逗号。

举例2

使用 group_concat() 和 group by 显示相同名字的人的 id 号:

将上面的 id 号从大到小排序,且用 ‘_’ 作为分隔符:

上面的查询中显示了以 name 分组的每组中所有的 id。接下来我们要查询以 name 分组的所有组的 id 和 email:

示例

group_concat([distinct] expr [,expr ...]

             [order by {unsigned_integer | col_name | expr}

                 [asc | desc] [,col_name ...]]

             [separator str_val])

测试数据

1. 查询所有学生的选课信息

select
    s.stu_id         as  studentid,
    s.stu_name       as  studentname,
    c.course_id      as  courseid,
    c.course_name    as  studentcourse
from
    student s
left join
    stu_course sc
on
    s.stu_id = sc.stu_id
left join
    course c
on
    sc.course_id = c.course_id

2 使用 group_concat() 函数将结果分组归集

select
    s.stu_id       as  studentid,
    s.stu_name     as  studentname,
    group_concat(c.course_id)    as  courseid,
    group_concat(c.course_name)  as  studentcourse
from
    student s
left join
    stu_course sc
on
    s.stu_id = sc.stu_id
left join
    course c
on
    sc.course_id = c.course_id
group by
    studentid

使用 group_concat 时会将数值类型的数据转化成二进制 blob类 型,可以用cast(expr as type) 函数或 convert(expr, type) 函数将数值类型的数据转化成字符串:

select
    s.stu_id          as  studentid,
    s.stu_name     as  studentname,
    group_concat(cast(c.course_id as char))     as  courseid,
    group_concat(c.course_name)  as  studentcourse
from
    student s
left join
    stu_course sc
on
    s.stu_id = sc.stu_id
left join
    course c
on
    sc.course_id = c.course_id
group by
    studentid

3 若要将第一条记录中 courseid 按照从小到大的方式归集

则可以在使用 group_concat() 时加上 order by

select
    s.stu_id          as  studentid,
    s.stu_name     as  studentname,
    group_concat(cast(c.course_id as char) order by c.course_id) as courseid,
    group_concat(c.course_name)  as  studentcourse
from
    student s
left join
    stu_course sc
on
    s.stu_id = sc.stu_id
left join
    course c
on
    sc.course_id = c.course_id
group by
    studentid

但我们发现,虽然 courseid 这一列的数据按照从小到大的顺序排序了,但另一列studentcourse 对应的数据却并没有跟着变,这也算是 group_concat 的一个缺点了。

若有人知晓如何让另一列也跟着变,还请不吝告知。

4 改变分隔符

group_concat 默认的分隔符是逗号(”,”),若想换成其他分隔符,可以用 separator 关键字:

select
    s.stu_id       as  studentid,
    s.stu_name     as  studentname,
    group_concat(cast(c.course_id as char) order by c.course_id separator '/')    as  courseid,
    group_concat(c.course_name separator '|')   as  studentcourse
from
    student s
left join
    stu_course sc
on
    s.stu_id = sc.stu_id
left join
    course c
on
    sc.course_id = c.course_id
group by
    studentid

数据库

create table `users` (
  `id` bigint(20) unsigned not null auto_increment,
  `name` varchar(255) collate utf8mb4_unicode_ci not null,
  `email` varchar(255) character set utf8 default null,
  `email_verified_at` timestamp null default null,
  `password` varchar(255) collate utf8mb4_unicode_ci not null,
  `remember_token` varchar(100) collate utf8mb4_unicode_ci default null,
  `created_at` timestamp null default null,
  `updated_at` timestamp null default null,
  `deleted_at` timestamp null default null on update current_timestamp,
  primary key (`id`)
) engine=innodb auto_increment=50078 default charset=utf8mb4 collate=utf8mb4_unicode_ci;
insert into `users` (`id`, `name`, `email`, `email_verified_at`, `password`, `remember_token`, `created_at`, `updated_at`, `deleted_at`) values ('77', '', null, null, '', null, null, null, null);
insert into `users` (`id`, `name`, `email`, `email_verified_at`, `password`, `remember_token`, `created_at`, `updated_at`, `deleted_at`) values ('5577', '', '55@qq.com', null, '', null, null, null, null);
insert into `users` (`id`, `name`, `email`, `email_verified_at`, `password`, `remember_token`, `created_at`, `updated_at`, `deleted_at`) values ('50010', 'willem', '11@qq.com', null, '', null, null, null, '2022-04-07 14:03:11');
insert into `users` (`id`, `name`, `email`, `email_verified_at`, `password`, `remember_token`, `created_at`, `updated_at`, `deleted_at`) values ('50012', 'wgchen', '22@qq.com', null, '', null, null, null, '2022-04-07 14:03:16');
insert into `users` (`id`, `name`, `email`, `email_verified_at`, `password`, `remember_token`, `created_at`, `updated_at`, `deleted_at`) values ('50018', 'ycc', '33@qq.com', null, '', null, null, null, '2022-04-07 14:03:23');
insert into `users` (`id`, `name`, `email`, `email_verified_at`, `password`, `remember_token`, `created_at`, `updated_at`, `deleted_at`) values ('50077', '77', '', null, '', null, null, null, '2022-04-07 14:06:39');

案例

1 mysql 中某个字段前或后添加字符

update optional_product
set cate_path = concat('|',cate_path,'|')

2 mysql 中批量替换某个字段的值:replace

例如我们有一个表:mxd_goods 中字段 goods_pic 的值要全部去掉 goods/

现在要将该表中的所有 goods_pic 字段的值去掉 goods/

update  mxd_goods set goods_pic= replace(goods_pic, 'goods/', '');

注:goods_pic 是表字段值,goods/ 是被替换的值,即搜索的值,‘’是替换后的值,此处替换为空,意思是去掉了 goods/

一定要加 where id =数字 ,否则将是全表修改哦。

怎么撤销呢?

update mxd_goods
set goods_pic = replace (goods_pic, 'g_', 'goods/g_')
where
	goods_id = 1849;

3 substring(a,b,c) 截取字符串

substring(a,b,c): 表示截取,其中第一个参数a表示被截取的参数对象,第二个参数b表示从哪个位置开始截取,第三个参数c表示要截取的长度

举例如下:

select  substring("hello",2,2);

表示从字符串 ’hello’ 中的 ’e’ 字符开始截取两个字符

运行结果如下:

4 mysql 删除最后一个字符

使用 substring 的任何解决方案只会通过删除最后一个字符来显示字段的内容.它实际上不会更新列的内容.如果这是你想要的(即使用 select), 那么 substring 就足够了.

但是,如果要实际更新列的值,可以尝试以下操作:

update <table_name>
set <column_name> = concat(left(<column_name>, char_length(<column_name>) -1), '')
where <condition>;
select
	substr(
		title,
		1,
		char_length(title) - 1
	)
from
	hhir_crm_email_send_content
where
	id = 14;

项目案例

select
	`record`.`id`,
	`record`.`fund_name`,
	`record`.`report_type`,
	`record`.`number`,
	`record`.`year`,
	`record`.`quarter`,
	`record`.`notice_time`,
	`record`.`customer_sub_name`,
	`record`.`legal_subject_name`,
	`record`.`send_status`,
	`record`.`created_at`,
	`report_send`.`report_name`,
	`send_content`.`title` as `email_title`,
	group_concat(
			`contact_link`.`contact_name`,
			concat('(', `contact_link`.`contact_email`, ');') separator ''
		) as contacts
from
	`hhir_crm_email_record` as `record`
left join `hhir_crm_email_report_send` as `report_send` on `report_send`.`email_record_id` = `record`.`id`
and `report_send`.`valid` = 1
left join `hhir_crm_email_send_content` as `send_content` on `send_content`.`email_record_id` = `record`.`id`
and `send_content`.`valid` = 1
left join `hhir_crm_email_contact_link` as `contact_link` on `contact_link`.`email_record_id` = `record`.`id`
and `contact_link`.`valid` = 1
where
	`record`.`valid` = 1
group by `record`.`id`

select
	id,
	group_concat(
		title,
		concat('(', cc_emails, ');') separator ''
	) as email_title
from
	hhir_crm_email_send_content
where
	id in (12, 13)

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com