MySQL concat_ws和group_concat函數(shù)有什么區(qū)別?一文搞懂
一、concat() 函數(shù)
1、功能:將多個字符串連接成一個字符串。
2、語法:concat(str1, str2,…)
返回結(jié)果為連接參數(shù)產(chǎn)生的字符串,如果有任何一個參數(shù)為 null,則返回值為 null。
舉例1

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

上面有一行為 null 是因為 users 表中有一行的 email 值為 null。
舉例2
在例1的結(jié)果中三個字段 id,name,email 的組合沒有分隔符,我們可以加一個逗號作為分隔符。
select CONCAT(id,',',name,',',email) as userinfo from users;

二、concat_ws() 函數(shù)
1、功能:和 concat() 一樣,將多個字符串連接成一個字符串,但是可以一次性指定分隔符~(concat_ws 就是 concat with separator)
2、語法:concat_ws(separator, str1, str2, …)
說明:第一個參數(shù)指定分隔符。需要注意的是分隔符不能為 null,如果為 null,則返回結(jié)果為 null。
舉例
使用 concat_ws() 將 分隔符指定為逗號。
select CONCAT_WS(',',id,name,email) as userinfo from users;
把分隔符指定為 null,結(jié)果全部變成了 null。

三、group_concat() 函數(shù)
前言:
在有 group by 的查詢語句中,select 指定的字段要么就包含在 group by 語句的后面,作為分組的依據(jù),要么就包含在聚合函數(shù)中。
舉例1

該例查詢了name 相同的的人中最小的 id。如果我們要查詢 name 相同的人的所有的id呢?
當(dāng)然我們可以這樣查詢:

但是這樣同一個名字出現(xiàn)多次,看上去非常不直觀。
有沒有更直觀的方法,既讓每個名字都只出現(xiàn)一次,又能夠顯示所有的名字相同的人的 id呢? ——使用 group_concat()
1、功能:將 group by 產(chǎn)生的同一個分組中的值連接起來,返回一個字符串結(jié)果。
2、語法:
group_concat([DISTINCT] 要連接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])
說明:
通過使用 distinct 可以排除重復(fù)值;
如果希望對結(jié)果中的值進行排序,可以使用 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])
測試數(shù)據(jù)

1. 查詢所有學(xué)生的選課信息
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() 函數(shù)將結(jié)果分組歸集
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 時會將數(shù)值類型的數(shù)據(jù)轉(zhuǎn)化成二進制 BLOB類 型,可以用CAST(expr AS type) 函數(shù)或 CONVERT(expr, type) 函數(shù)將數(shù)值類型的數(shù)據(jù)轉(zhuǎn)化成字符串:
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

但我們發(fā)現(xiàn),雖然 courseId 這一列的數(shù)據(jù)按照從小到大的順序排序了,但另一列studentCourse 對應(yīng)的數(shù)據(jù)卻并沒有跟著變,這也算是 GROUP_CONCAT 的一個缺點了。
若有人知曉如何讓另一列也跟著變,還請不吝告知。
4 改變分隔符
GROUP_CONCAT 默認的分隔符是逗號(”,”),若想換成其他分隔符,可以用 SEPARATOR 關(guān)鍵字:
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

數(shù)據(jù)庫
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/。

現(xiàn)在要將該表中的所有 goods_pic 字段的值去掉 goods/ 。
update mxd_goods set goods_pic= replace(goods_pic, 'goods/', '');
注:goods_pic 是表字段值,goods/ 是被替換的值,即搜索的值,‘’是替換后的值,此處替換為空,意思是去掉了 goods/。
一定要加 where id =數(shù)字 ,否則將是全表修改哦。

怎么撤銷呢?
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): 表示截取,其中第一個參數(shù)a表示被截取的參數(shù)對象,第二個參數(shù)b表示從哪個位置開始截取,第三個參數(shù)c表示要截取的長度
舉例如下:
SELECT SUBSTRING("hello",2,2);
表示從字符串 ’hello’ 中的 ’e’ 字符開始截取兩個字符
運行結(jié)果如下:

4 MySQL 刪除最后一個字符
使用 SUBSTRING 的任何解決方案只會通過刪除最后一個字符來顯示字段的內(nèi)容.它實際上不會更新列的內(nèi)容.如果這是你想要的(即使用 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)


總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL數(shù)據(jù)庫操作常用命令小結(jié)
這篇文章主要介紹了MySQL數(shù)據(jù)庫操作常用命令小結(jié),例如創(chuàng)建數(shù)據(jù)庫、使用數(shù)據(jù)庫、查看數(shù)據(jù)庫、數(shù)據(jù)庫編碼操作等命令講解,需要的朋友可以參考下2014-12-12
MySQL學(xué)習(xí)第一天 第一次接觸MySQL
這篇文章是學(xué)習(xí)MySQL的第一篇文章,開啟了探究MySQL的奇妙旅程,內(nèi)容主要是對MySQL的基礎(chǔ)知識進行學(xué)習(xí),了解,感興趣的小伙伴們可以參考一下2016-05-05
MySQL安裝提示"請鍵入NET HELPMSG 3534以獲得更多的幫助"的解決辦法
這篇文章主要介紹了MySQL安裝提示"請鍵入NET HELPMSG 3534以獲得更多的幫助"的解決辦法2017-03-03
關(guān)于Win10下MySQL5.7.17免安裝版基本配置教程(圖文詳解)
這數(shù)據(jù)庫應(yīng)用是一個應(yīng)用系統(tǒng)不可或缺的部分,關(guān)系型數(shù)據(jù)庫應(yīng)用大同小異,這里選擇MySQL作為數(shù)據(jù)庫平臺。下面通過本文給大家介紹關(guān)于Win10下MySQL5.7.17免安裝版基本配置教程(圖文詳解),需要的朋友可以參考下2017-06-06
大批量數(shù)據(jù)用mysql批量更新數(shù)據(jù)的4種方法總結(jié)
這篇文章主要給大家介紹了關(guān)于大批量數(shù)據(jù)用mysql批量更新數(shù)據(jù)的4種方法,要在MySQL中新增大批量數(shù)據(jù),可以通過以下幾種方法來實現(xiàn),文中給出了詳細的代碼示例,需要的朋友可以參考下2024-05-05

