MySQL GROUP_CONCAT() 函数使用指南

MySQL GROUP_CONCAT() 函数将一个分组中指定的列或表达式的值连接成一个字符串并返回。

GROUP_CONCAT() 语法

这里是 MySQL GROUP_CONCAT() 函数的语法:

GROUP_CONCAT(
    [DISTINCT] expr [, expr2 ...]
    [ORDER BY ...]
    [SEPARATOR separator]
)

我们通常在 MySQL 中按如下方式使用 GROUP_CONCAT() 函数:

SELECT GROUP_CONCAT(expr), ...
FROM table_name
[WHERE ...]
[GROUP BY group_expr1, group_expr2, ...];

参数

expr [, expr2 ...]
必须的。它指定了要连接的一个或者多个列或表达式。
ORDER BY
可选的。它用于对要连接的内容排序。
SEPARATOR separator
可选的。separator 连接符。默认是 ,

返回值

MySQL GROUP_CONCAT(expr) 函数返回一个字符串,它将通过列或者表达式指定的内容连接起来。

如果结果集没有任何行,此函数将返回 NULL

GROUP_CONCAT() 示例

我们将通过 student_score 表进行演示。

首先,让我们使用如下语句创建表 student_score

DROP TABLE IF EXISTS `student_score`;
CREATE TABLE `student_score` (
    `id` INT PRIMARY KEY AUTO_INCREMENT,
    `name` VARCHAR(255) NOT NULL,
    `subject` VARCHAR(255) NOT NULL,
    `score` INT NOT NULL
);

这里我们创建了表用于存储学生的成绩,这个表有 4 个列组成:

  • id 是主键
  • name 是学生的名字
  • subject 是学生的科目
  • score 是学生的成绩

其次,让我们插入一些数据用于演示:

INSERT INTO `student_score` (`name`, `subject`, `score`)
VALUES
    ('Tom', 'Math', 80),
    ('Tom', 'English', 90),
    ('Tim', 'English', 98);

以下是表中的数据:

+----+------+---------+-------+
| id | name | subject | score |
+----+------+---------+-------+
|  1 | Tom  | Math    |    80 |
|  2 | Tom  | English |    90 |
|  3 | Tim  | English |    98 |
+----+------+---------+-------+

现在,我们可以使用 GROUP_CONCAT() 函数获取每个人参加的考试科目的列表,如下:

SELECT
    name AS `Name`,
    GROUP_CONCAT(subject) AS `Subjects`
FROM student_score
GROUP BY name;
+------+--------------+
| Name | Subjects     |
+------+--------------+
| Tim  | English      |
| Tom  | Math,English |
+------+--------------+

这里,我们按照 name 分组,并使用 GROUP_CONCAT() 函数将每组中的 subject 列的内容连接起来。

上面的语句中,由于未指定分隔符,因此使用了逗号 , 进行连接。如果我们想要使用其他的分隔符(比如: /),可是使用 SEPARATOR 指定:

SELECT
    name AS `Name`,
    GROUP_CONCAT(subject SEPARATOR '/') AS `Subjects`
FROM student_score
GROUP BY name;
+------+--------------+
| Name | Subjects     |
+------+--------------+
| Tim  | English      |
| Tom  | Math/English |
+------+--------------+

如果我们想要每个组中连接的科目按照科目的名称排序,可以使用 ORDER BY,如下:

SELECT
    name AS `Name`,
    GROUP_CONCAT(subject ORDER BY subject SEPARATOR '/') AS `Subjects`
FROM student_score
GROUP BY name;
+------+--------------+
| Name | Subjects     |
+------+--------------+
| Tim  | English      |
| Tom  | English/Math |
+------+--------------+

这里,由于设定了 ORDER BY subject,那么对于 Tom 而言, English 排到了 Math 的前面。

如果我们想要同时拼接科目和成绩,请使用如下语句:

SELECT
    name AS `Name`,
    GROUP_CONCAT(
        subject, score
        ORDER BY subject
        SEPARATOR '/'
    ) AS `Scores`
FROM student_score
GROUP BY name;
+------+------------------+
| Name | Scores           |
+------+------------------+
| Tim  | English98        |
| Tom  | English90/Math80 |
+------+------------------+

这里,我们在 GROUP_CONCAT() 函数中传入了多个列,subjectscore。 注意输出,科目和成绩直接拼接在了一起,中间没有连接符。

如果我们想要在科目和成绩之间使用一个连接符 -, 请使用如下语句:

SELECT
    name AS `Name`,
    GROUP_CONCAT(
        CONCAT(subject, '-'), score
        ORDER BY subject
        SEPARATOR '/'
    ) AS `Scores`
FROM student_score
GROUP BY name;
+------+--------------------+
| Name | Scores             |
+------+--------------------+
| Tim  | English-98         |
| Tom  | English-90/Math-80 |
+------+--------------------+

注意,我们在这里使用了表达式 CONCAT(subject, '-') 作为 GROUP_CONCAT() 函数的一个输入参数,它的目的是在科目的后面连接一个 ‘-’。

或者我们使用 CONCAT_WS() 函数来达到相同的目的:

SELECT
    name AS `Name`,
    GROUP_CONCAT(
        CONCAT_WS('-', subject, score)
        ORDER BY subject
        SEPARATOR '/'
    ) AS `Scores`
FROM student_score
GROUP BY name;
+------+--------------------+
| Name | Scores             |
+------+--------------------+
| Tim  | English-98         |
| Tom  | English-90/Math-80 |
+------+--------------------+