版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ycd500756/article/details/84191459
1.背景
sql中分组并不陌生,使用起来也不难,见名知意就是将字段具有形同的记录值分为一组。最近的工作中的业务也是经常需要分组分组,所以写点东西记录一下分组常用场景。
2.数据准备
1.运行环境为mysql,版本为5.7.22
2.简单建立一个员工表(tb_emp),表结构和表的字段值如下:
CREATE TABLE `tb_emp` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT COMMENT '员工id',
`name` varchar(20) NOT NULL COMMENT '员工姓名',
`job_id` smallint(5) DEFAULT NULL COMMENT '工种id',
`dept_id` smallint(5) unsigned DEFAULT NULL COMMENT '部门id',
PRIMARY KEY (`id`),
KEY `idx_tbEmp_deptId` (`dept_id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
mysql> SELECT * FROM tb_emp;
+----+--------+--------+---------+
| id | name | job_id | dept_id |
+----+--------+--------+---------+
| 1 | Mark | 1 | 1 |
| 2 | Sammi | 1 | 2 |
| 3 | Abel | 1 | 2 |
| 4 | Dannel | 2 | 2 |
| 7 | Eason | 1 | 3 |
| 8 | Sa | 2 | 3 |
| 10 | Gigi | 2 | 3 |
+----+--------+--------+---------+
7 rows in set
3.语法结构
SELECT 分组函数,查询列表(要求出现group by的后面)
FROM 原始表
WHERE 分组前的筛选条件
GROUP BY 分组的列表
HAVING 分组后的筛选条件
ORDER BY
LIMIT
3.单个字段分组
需求1: 查找员工表中各个部门的员工个数
mysql> SELECT COUNT(1) coun,dept_id FROM tb_emp GROUP BY dept_id;
+------+---------+
| coun | dept_id |
+------+---------+
| 1 | 1 |
| 3 | 2 |
| 3 | 3 |
+------+---------+
3 rows in set
需求2(加上筛选条件):查找员工表中 部门的员工id大于1 而且 部门的员工个数大于2的部门
mysql> SELECT COUNT(1) coun,dept_id
FROM tb_emp
WHERE id>1
GROUP BY dept_id
HAVING coun > 2;
+------+---------+
| coun | dept_id |
+------+---------+
| 3 | 2 |
| 3 | 3 |
+------+---------+
2 rows in set
分析:部门的员工id大于1
,过滤字段id
在原始表(tb_emp)就可以找到,该筛选可以在分组前
就进行筛选,
所以筛选语句写在where
中。部门的员工个数大于2
,该筛选的数据源是基于分组后
才能进行过滤,那么该条件的筛选语句需要写在having
中。
4.基于多个字段进行分组
需求:查找员工表中各个部门各个工种的员工个数。
1.先来看看 根据部门分组
后结果 和 根据工种分组
的结果。
mysql> SELECT COUNT(1) coun,dept_id FROM tb_emp GROUP BY dept_id ;
+------+---------+
| coun | dept_id |
+------+---------+
| 1 | 1 |
| 3 | 2 |
| 3 | 3 |
+------+---------+
3 rows in set
mysql> SELECT COUNT(1) coun,job_id FROM tb_emp GROUP BY job_id ;
+------+--------+
| coun | job_id |
+------+--------+
| 4 | 1 |
| 3 | 2 |
+------+--------+
2 rows in set
2.根据部门和工种进行分组, 即相同的部门中相同的工种分为一组。
mysql> SELECT COUNT(1) coun,job_id ,dept_id FROM tb_emp GROUP BY job_id ,dept_id;
+------+--------+---------+
| coun | job_id | dept_id |
+------+--------+---------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 1 | 1 | 3 |
| 1 | 2 | 2 |
| 2 | 2 | 3 |
+------+--------+---------+
5 rows in set
5.根据表达式或者函数进行分组
这种使用场景较少
需求:根据员工的名称的长度进行分组,并且计算各组的员工个数。
mysql> SELECT COUNT(1) coun,LENGTH(name) name_len FROM tb_emp GROUP BY name_len;
+------+----------+
| coun | name_len |
+------+----------+
| 1 | 2 |
| 3 | 4 |
| 2 | 5 |
| 1 | 6 |
+------+----------+
4 rows in set
6.总结
1.分组中是筛选条件可以分为两种:
- 分组前筛选:数据源是原始表(即在mysql中可以看到的表),使用where关键字,sql位置在group by 前面;
- 分组后筛选:数据源是基于分组后的结果集,使用having关键字,sql位置在group by后面。
2.多个字段分组用逗号分开即可;
3.分组操作后可以添加排序操作。
last edit date: 2018-11-17
location:广州-海珠区-西畔里