【DataBase】MySQL 13 分组查询

分组查询 GROUP BY

-- group by 子句
-- 要注意!group by 子句一定是放在WHERE的后面
/*
SELECT 分组函数,列(要求出现在GROUP BY后面)
FROM 表
[WHERE 筛选条件]
GROUP BY 分组列表
[ORDER BY 子句]

查询列表必须特殊,要求是分组函数和GROUP BY后出现的
*/

 

查询每个部门的平均工资

单使用AVG函数只能查询所有部门一起的平均工资

-- 查询每个部门的平均工资:
SELECT AVG(`salary`) 
FROM `employees`;

 

引入GROUP BY子句 ,对部门进行一个分组

SELECT AVG(`salary`),`department_id`
FROM `employees`
GROUP BY `department_id`;

 

查询每个工种的最高工资

# 查询每个工种的最高工资,
SELECT MAX(`salary`),`job_id`
FROM `employees`
GROUP BY `job_id`;

 

可以发现,使用GROUP BY子句的前提条件是必须要有聚合函数【组合函数】的查询使用

它们和分组查询形成了一种依赖关系,二者缺一不可

 

添加分组前,筛选条件

# 前置加入筛选条件
-- 查询邮箱中包含a字符的,每个部门的平均工资
SELECT AVG(`salary`),`department_id`
FROM `employees`
WHERE `email` LIKE %a%
GROUP BY `department_id`;

# 查询有奖金的每个人领导手下员工的最高工资
SELECT MAX(`salary`),`manager_id`
FROM `employees`
WHERE `commission_pct` IS NOT NULL
GROUP BY `manager_id`;

 

添加复杂的筛选条件

【需要对分组后的结果再执行筛选 使用Having】

# 复杂筛选条件
# 案例 查询哪些部门的员工个数大于2
SELECT COUNT(*) as counts,`department_id`
FROM `employees`
group by `department_id`
Having counts > 2; -- 对分组之后再进行筛选的,使用Having子句充当where

# 查询每个工种有奖金的员工的最高工资 > 12000 的工种编号,和最高工资
SELECT MAX(`salary`) maxSalary,`job_id`
FROM `employees`
where `commission_pct` IS NOT NULL
GROUP BY `job_id`
having maxSalary > 12000 ;

# 查询每个领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个,以及最低工资
SELECT MIN(`salary`),`manager_id`
FROM `employees`
WHERE `manager_id` > 102
GROUP by `manager_id`
having MIN(`salary`) > 5000;

 

按表达式进行分组

要注意一点:Oracle是不支持GROUP BY & HAVING SQL语句的

-- 按员工姓名的长度分组,查询每一组员工个数,筛选员工个数大于5的

-- 先查询每个长度的员工个数
SELECT COUNT(员工个数),LENGTH(`last_name`) AS "名字长度分组"
FROM `employees`
GROUP BY LENGTH(`last_name`);

-- 再筛选大于5的个数
SELECT COUNT(员工个数) AS c,LENGTH(`last_name`) AS "名字长度分组"
FROM `employees`
GROUP BY LENGTH(`last_name`)
HAVING c > 5;

 

按多个字段分组查询

-- 查询每个部门的每个工种的员工的平均工资

-- 先确定要查询的要素
SELECT AVG(`salary`),`job_id`,`department_id`
-- 查询的要素来自于哪张表
FROM `employees`
-- 对查询的条件进行判断
GROUP BY `job_id`,`department_id`;

 

分组查询是支持排序的

-- 查询每个部门的每个工种的员工的平均工资,按平均工资从高到底显示
SELECT AVG(`salary`),`job_id`,`department_id`
FROM `employees`
GROUP BY `job_id`,`department_id`
ORDER BY AVG(`salary`) DESC;

-- 增加部门ID不是null的情况
SELECT AVG(`salary`),`job_id`,`department_id`
FROM `employees`
WHERE `department_id` IS NOT NULL
GROUP BY `job_id`,`department_id`
ORDER BY AVG(`salary`) DESC;

-- 平均工资还要高于10000的
SELECT AVG(`salary`),`job_id`,`department_id`
FROM `employees`
WHERE `department_id` IS NOT NULL
GROUP BY `job_id`,`department_id`
HAVING AVG(`salary`) > 10000 -- 要放在排序的前面,排序留在最后面执行
ORDER BY AVG(`salary`) DESC;

 

GROUP  BY的总结:

- 分组前筛选 

  数据源是 原始表【就是从数据库查询的表】

  在GROUP BY 之前 使用【WHERE】子句

- 分组后筛选 

  数据源是 虚拟表【就是从分组之后返回的结果集】

  在GROUP BY 之后 使用【HAVING】子句

- 支持多字段分组查询

  多字段使用逗号隔开

  字段没有顺序要求

- 支持表达式 & 函数  

- 支持排序查询

  排序子句放在SQL的结尾

 

练习案例:

-- 1、查询个工种ID的员工工资的聚合函数,并按照工种升序
SELECT `job_id`,MAX(`salary`),MIN(`salary`),AVG(`salary`),SUM(`salary`)
FROM `employees`
GROUP BY `job_id`
ORDER BY `job_id` ASC;

-- 2查询 员工工资最高最低的差距
SELECT MAX(`salary`),MIN(`salary`),MAX(`salary`) - MIN(`salary`) 相差金额
FROM `employees`;

-- 3查询各个管理者手下员工的最低工资,不得低于6000,没有管理者不计算在内

-- 歧义SQL 不正确的筛选>6000
SELECT `manager_id`,MIN(`salary`)
FROM `employees`
WHERE `salary` > 6000 AND `manager_id` IS NOT NULL -- 在分组之前筛选6000
GROUP BY `manager_id`;

-- 正确SQL
SELECT `manager_id`,MIN(`salary`)
FROM `employees`
WHERE `manager_id` IS NOT NULL -- 在分组之前筛选6000无效
GROUP BY `manager_id`
HAVING MIN(`salary`) > 6000;

-- 4 查询所有部门编号,员工数量,和工资平均值,按工资平均值降序
SELECT AVG(`salary`),COUNT(员工数量),`department_id`
FROM `employees`
GROUP BY `department_id`
ORDER BY AVG(`salary`) ASC;

-- 如果没有部门就不算在内的话...
SELECT AVG(`salary`),COUNT(员工数量),`department_id`
FROM `employees`
WHERE `department_id`  IS NOT NULL
GROUP BY `department_id` 
ORDER BY AVG(`salary`) ASC;

-- 5 查询每个具有工种ID的员工人数
SELECT `job_id`,COUNT(人数)
FROM `employees`
GROUP BY `job_id`;

 

【DataBase】MySQL 13 分组查询

上一篇:转发两篇很详细实用的网页


下一篇:js事件循环机制