mysql group_concat

 

group_concat()函数

 

前言:在有group by的查询语句中,select指定的字段要么就包含在group by语句的后面,作为分组的依据,要么就包含在聚合函数中。(有关group by的知识请戳:浅析SQL中Group By的使用)。

 

例5:

 

 

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

 

当然我们可以这样查询:

 

例6:

 

 

但是这样同一个名字出现多次,看上去非常不直观。有没有更直观的方法,既让每个名字都只出现一次,又能够显示所有的名字相同的人的id呢?——使用group_concat()

 

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

 

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

 

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

 

3、举例:

 

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

 

 

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

 

 

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

 

 
 
=====================================================================================================

 

以id分组,把price字段的值在一行打印出来,分号分隔 

select id,group_concat(price separator ';') from goods group by id;  

+------+----------------------------------+
| id| group_concat(price separator ';') |
+------+----------------------------------+
|1 | 10;20;20 |
|2 | 20|
|3 | 200;500 |
+------+----------------------------------+
3 rows in set (0.00 sec)

=============================================

CREATE TABLE `grade1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`stuName` varchar(22) DEFAULT NULL,
`course` varchar(22) DEFAULT NULL,
`score` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of grade1
-- ----------------------------
INSERT INTO `grade1` VALUES ('1', '张三', '语文', '91');
INSERT INTO `grade1` VALUES ('2', '张三', '数学', '90');
INSERT INTO `grade1` VALUES ('3', '张三', '英语', '87');
INSERT INTO `grade1` VALUES ('4', '李四', '语文', '79');
INSERT INTO `grade1` VALUES ('5', '李四', '数学', '95');
INSERT INTO `grade1` VALUES ('6', '李四', '英语', '80');
INSERT INTO `grade1` VALUES ('7', '王五', '语文', '77');
INSERT INTO `grade1` VALUES ('8', '王五', '数学', '81');
INSERT INTO `grade1` VALUES ('9', '王五', '英语', '89'); 

表内容如上图

先看看group_concat语法:
group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator ‘分隔符’])

以stuName分组,把score字段的值打印在一行,逗号分隔(默认)
select GROUP_CONCAT(score),stuName from grade1 GROUP BY stuName;
1
2
其结果是:


那比如现在要查询出 语数外三门课的最低分,还有哪个学生考的?该怎么写??

select GROUP_CONCAT(stuName ORDER BY score ASC),
min(score) as score,
course
from
grade1
group by
course;  
其结果是:


在结果中的第一列 ,有很多姓名并且以逗号隔开,其实这里的姓名就是按照score 升序排的(GROUP_CONCAT(stuName ORDER BY score ASC)),比如第一行的”王五,张三,李四”,就是按照数学的分数由低到高排序的,所以王五是数学分数最低的,那么我们只需要把这个字符串截取第一个人的名字就可以了,我们使用SUBSTRING_INDEX

/*SUBSTRING_INDEX以逗号分隔,取第一个值*/
select SUBSTRING_INDEX(GROUP_CONCAT(stuName ORDER BY score ASC),',',1),
min(score) as score,
course
from
grade1
group by
course;  
其结果是:


如果有并列最低分只能取到一个学生,可以这样修改,并列最低都可以查出:

SELECT
stuName,
score,
course
FROM
grade1
WHERE
(score, course) IN (
SELECT
min(score),
course
FROM
grade1
GROUP BY
course
); 
第一种如果有并列最低分只能取到一个学生,第二种没问题,不过效率可能会稍差点,数据量少就无所谓了

还有一种写法(不知道效率怎么样):

SELECT
g.`id`,g.`course`,g.`score`,g.`stuName`
FROM
(SELECT
course,
SUBSTRING_INDEX(
GROUP_CONCAT(score
ORDER BY score ASC),
',',
1
) AS score
FROM
grade1
GROUP BY course) AS t
LEFT JOIN grade1 AS g
ON (
t.course = g.`course`
AND t.score = g.`score`
)
---------------------  

MySQL中group_concat函数


完整的语法如下:


group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])

 

基本查询

 

Sql代码  收藏代码
  1. select * from aa;  


+------+------+
| id| name |
+------+------+
|1 | 10|
|1 | 20|
|1 | 20|
|2 | 20|
|3 | 200 |
|3 | 500 |
+------+------+
6 rows in set (0.00 sec)

 

以id分组,把name字段的值打印在一行,逗号分隔(默认)

 

Sql代码  收藏代码
  1. select id,group_concat(namefrom aa group by id;  


+------+--------------------+
| id| group_concat(name) |
+------+--------------------+
|1 | 10,20,20|
|2 | 20 |
|3 | 200,500|
+------+--------------------+
3 rows in set (0.00 sec)

 

以id分组,把name字段的值打印在一行,分号分隔

 

Java代码  收藏代码
  1. select id,group_concat(name separator ';') from aa group by id;  


+------+----------------------------------+
| id| group_concat(name separator ';') |
+------+----------------------------------+
|1 | 10;20;20 |
|2 | 20|
|3 | 200;500 |
+------+----------------------------------+
3 rows in set (0.00 sec)

 

以id分组,把去冗余的name字段的值打印在一行,


逗号分隔

 

Sql代码  收藏代码
  1. select id,group_concat(distinct namefrom aa group by id;  


+------+-----------------------------+
| id| group_concat(distinct name) |
+------+-----------------------------+
|1 | 10,20|
|2 | 20 |
|3 | 200,500 |
+------+-----------------------------+
3 rows in set (0.00 sec)

 

以id分组,把name字段的值打印在一行,逗号分隔,以name排倒序

 

Sql代码  收藏代码
  1. select id,group_concat(name order by name descfrom aa group by id;  


+------+---------------------------------------+
| id| group_concat(name order by name desc) |
+------+---------------------------------------+
|1 | 20,20,10 |
|2 | 20|
|3 | 500,200|
+------+---------------------------------------+
3 rows in set (0.00 sec)

 

测试sql,项目中用到的。

Sql代码  收藏代码
  1. SELECT  
  2.         EMPLOYEES.EMPID  
  3.         ,EMPLOYEES.EMPNAME  
  4.         ,DEPARTMENTS.DEPARTMENTNAME  
  5.         ,EMPLOYEES.DEPTID  
  6.         ,EMPLOYEES.EMPPWD  
  7.         ,EMPLOYEES.INSIDEEMAIL  
  8.         ,EMPLOYEES.OUTSIDEEMAIL  
  9.         ,EMPLOYEES.DELEFLAG  
  10.         ,EMPLOYEES.EMPCLASS  
  11.         ,(CONCAT('[', <span style="color: #ff0000;">GROUP_CONCAT</span>  
  12. (ROLE.Role_Name SEPARATOR '],['), ']')) AS ROLENAME  
  13.         ,(concat( '[', (  
  14.             SELECT  
  15.                     <span style="color: #ff0000;">GROUP_CONCAT</span>  
  16. (DEPARTMENTS.DEPARTMENTNAME separator '],[')  
  17.                 FROM  
  18.                     EMP_ROLE_DEPT  
  19.                         LEFT JOIN DEPARTMENTS  
  20.                             ON (  
  21.                                 DEPARTMENTS.DEPARTMENTID = EMP_ROLE_DEPT.DEPTID  
  22.                                 AND DEPARTMENTS.DELEFLAG = 0  
  23.                             )  
  24.                 GROUP BY  
  25.                     EMP_ROLE_DEPT.EMPID  
  26.                 HAVING  
  27.                     EMP_ROLE_DEPT.EMPID = EMPLOYEES.EMPID  
  28.         ),']')) AS DEPARTMENTRIGHT  
  29.     FROM  
  30.         EMPLOYEES  
  31.             LEFT JOIN DEPARTMENTS  
  32.                 ON (  
  33.                     DEPARTMENTS.DEPARTMENTID = EMPLOYEES.DEPTID  
  34.                     AND DEPARTMENTS.DELEFLAG = 0  
  35.                 )  
  36.             LEFT JOIN ROLE_EMP  
  37.                 ON (ROLE_EMP.EMP_ID = EMPLOYEES.EMPID)  
  38.             LEFT JOIN ROLE  
  39.                 ON (ROLE_EMP.ROLE_ID = ROLE.ROLE_ID)  
  40. <span style="color: #ff0000;">    GROUP BY  
  41.         EMPLOYEES.EMPID</span>  
  42.   
  43.     HAVING  
  44.         EMPLOYEES.EMPID LIKE '%%'  
  45.         AND EMPLOYEES.EMPNAME LIKE '%%'  
  46.         AND EMPLOYEES.DELEFLAG = 0  
  47.         AND (  
  48.             EMPLOYEES.EMPCLASS = '1'  
  49.             OR EMPLOYEES.EMPCLASS = '2'  
  50.         )  
  51.         AND EMPLOYEES.DEPTID = '001' LIMIT 0  
  52.         ,16   

posted on 2018-11-23 13:45  小甜瓜安东泥  阅读(243)  评论(0)    收藏  举报