先来看看官方手册对 GROUP_CONCAT 说明:

此函数返回一个字符串,是查询结果集合中指定列非NULL值的串联。如果所有列都是NULL,则此函数返回NULL。完整语法如下:

GROUP_CONCAT([DISTINCT] expr [,expr ...]
             [ORDER BY {unsigned_integer | col_name | expr}
                 [ASC | DESC] [,col_name ...]]
             [SEPARATOR str_val])

GROUP_CONCAT 是一个聚合函数,通常跟 GROUP BY 一起使用。

假设有一个学生成绩表tb_score,数据如下:

id student subject score
1 张三 语文 92
2 张三 数学 79
3 张三 英语 92
4 张三 物理 83
5 李四 语文 87
6 李四 数学 94
7 李四 地理 75
8 李四 物理 92
9 张三 化学 90
10 王五 数学 98
11 王五 历史 72
12 王五 语文 85

 

按学生名字分组,统计每个人考试的科目,SQL如下:

mysql> SELECT student,
    -> GROUP_CONCAT(subject) AS subject_list
    -> FROM tb_score
    -> GROUP BY student;
+---------+------------------------------------+
| student | subject_list                       |
+---------+------------------------------------+
| 张三    | 语文,数学,英语,物理,化学           |
| 李四    | 语文,数学,地理,物理                |
| 王五    | 数学,历史,语文                     |
+---------+------------------------------------+

如果每个人的科目按分数从高到低,则为:

mysql> SELECT student,
    -> GROUP_CONCAT(subject ORDER BY score DESC) AS subject_list
    -> FROM tb_score
    -> GROUP BY student;
+---------+------------------------------------+
| student | subject_list                       |
+---------+------------------------------------+
| 张三    | 英语,语文,化学,物理,数学           |
| 李四    | 数学,物理,语文,地理                |
| 王五    | 数学,语文,历史                     |
+---------+------------------------------------+

默认的,GROUP_CONCAT 拼接字符串时分隔符为英文逗号,可以用 SEPARATOR 指定分隔符:

mysql> SELECT student,
    -> GROUP_CONCAT(subject SEPARATOR '-') AS subject_list
    -> FROM tb_score
    -> GROUP BY student;
+---------+------------------------------------+
| student | subject_list                       |
+---------+------------------------------------+
| 张三    | 语文-数学-英语-物理-化学           |
| 李四    | 语文-数学-地理-物理                |
| 王五    | 数学-历史-语文                     |
+---------+------------------------------------+

统计分数,张三有两个92分,我们只希望显示一个92分,可以用DISTINCT去重:

mysql> SELECT student,
    -> GROUP_CONCAT(DISTINCT score ORDER BY score) AS score_list
    -> FROM tb_score
    -> GROUP BY student;
+---------+-------------+
| student | score_list  |
+---------+-------------+
| 张三    | 79,83,90,92 |
| 李四    | 75,87,92,94 |
| 王五    | 72,85,98    |
+---------+-------------+

最后,这里有个陷阱,特别要注意:

GROUP_CONCAT 的拼接长度受变量 group_concat_max_len 的限制,该变量默认值为1024。如果 GROUP_CONCAT 的结果超过这个值,后面的字符将会被截断。可以到配置文件里更改 group_concat_max_len 的值,或者使用SQL语句动态更改,但要注意,它不能超过 max_allowed_packet 的值。

用SQL更改 group_concat_max_len :

SET [GLOBAL | SESSION] group_concat_max_len = val;

官方 group_concat_max_len 说明:

Property Value
Command-Line Format --group-concat-max-len=#
System Variable group_concat_max_len
Scope Global, Session
Dynamic Yes
SET_VAR Hint Applies Yes
Type Integer
Default Value 1024
Minimum Value 4
Maximum Value (64-bit platforms) 18446744073709551615
Maximum Value (32-bit platforms) 4294967295