语法:
⑥SELECT 分组函数,列(此列要出现在 GROUP BY的后面)
①FROM 表
②【WHERE 筛选条件】
③GROUP BY 分组的列
④【having 分组后的筛选】
⑦【ORDER BY 按什么排序】
注意:查询列表是特殊的,必须是分组函数后和GROUP BY后出现的字段
特点:
1.分组查询中的筛选条件分为两类
筛选的数据源不一样 | 位置 | 关键字 |
分组前筛选:原始表,库里真实存在的表 | GROUP BY 前 WHERE | WHERE |
分组后筛选:分组后的结果集 | GROUP BY 后 HAVING | HAVING |
- 分组函数做条件肯定放在having子句中:原因筛选条件原始表中没有
- 分组后的字段做筛选条件,放在where和having都行。
- 出于性能的考虑:能用分组前筛选的就优先使用分组前筛选
2.都可以按什么分组
- GROUP BY 子句支持单个字段分组,多个字段分组(字段之间用逗号隔开)没有顺序要求,也可以用表达式或函数
3.也可以添加排序,放在整个分组查询最后
GROUP BY、HAVING 都支持别名,where不支持别名
GROUP BY、HAVING后加别名。Oracle中不支持,MySQL支持
#查询每个部门的平均工资
SELECT AVG(salary) FROM employees;
#简单的分组查询
案例1:查询每个工种的最高工资
SELECT MAX(salary),job_id FROM employees GROUP BY job_id;
案例2:查询每个位置上的部门个数
SELECT COUNT(*),location_id FROM departments GROUP BY location_id;
#添加筛选条件
案例1:查询邮箱中包含字母a字符的,每个部门的平均工资
SELECT AVG(salary),department_id FROM employees WHERE email LIKE '%a%' GROUP BY department_id;
案例2:查询有奖金的每个领导手下员工的最高工资
SELECT MAX(salary),manager_id FROM employees WHERE commission_pct IS NOT NULL#有奖金 GROUP BY manager_id;
#添加复杂的筛选条件
案例1:查询那个部门的员工个数大于2
#1.查询每个部门的员工个数
SELECT COUNT(*),department_id FROM employees GROUP BY department_id;
#2.根据1.的结果进行筛选,查询哪个部门的员工个数大于2
SELECT COUNT(*),department_id FROM employees WHERE COUNT(*)>2 GROUP BY department_id;
报错无效的使用Invalid use of group function
WHERE是根据原始数据进行筛选,它要紧更着表后面,因为是:找表、筛选、显示、排序。
WHERE是分组前的筛选
这时候就需要新的关键字 HAVING,实现分组后的筛选
SELECT COUNT(*),department_id FROM employees GROUP BY department_id HAVING COUNT(*)>2;
#案例2:查询每个工种有奖金的员工的最高工资大于12000的工种编号和最高工资
思路
先分组再筛选
#1.查询每个工种有奖金的最高工资
SELECT MAX(salary),job_id FROM employees WHERE commission_pct IS NOT NULL GROUP BY job_id;
#2.根据1的结果继续筛选,最高工资>12000
SELECT MAX(salary),job_id FROM employees WHERE commission_pct IS NOT NULL GROUP BY job_id HAVING MAX(salary)>12000;
#案例3:查询领导编号大于102的每个领导手下的最低工资大于5000的领导编号是哪个,以及其最低工资
#1查询领导每个领导手下的最低工资
SELECT MIN(salary),manager_id FROM employees GROUP BY manager_id
查询出最低工资按照领导编号分组
#2.添加筛选条件
SELECT MIN(salary),manager_id FROM employees WHERE manager_id>102 GROUP BY manager_id HAVING MIN(salary)>5000;
如果筛选的条件原始表就有就使用where
如果结果需要在筛选的结果上筛选那么就用 HAVING
#按函数表达或函数分组
#案例1:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数大于5的有哪些
#1.查询每个员工的姓名长度
SELECT COUNT(*),LENGTH(last_name) AS len_name #查询员工的个数,姓名的长度 FROM employees#在employee表中 GROUP BY LENGTH(last_name)#按姓名的长度分组 HAVING COUNT(*)>5;
SELECT COUNT(*) AS C,LENGTH(last_name) AS len_name #查询员工的个数,姓名的长度 FROM employees#在employee表中 GROUP BY len_name#按姓名的长度分组 HAVING C>5;
GROUP BY、HAVING 都支持别名,where不支持别名
GROUP BY、HAVING后加别名。Oracle中不支持,MySQL支持
#按多个字段分组
#案例:查询每个部门每个工种的员工的平均工资
SELECT AVG(salary),department_id,job_id FROM employees GROUP BY department_id,job_id;
#添加排序
#案例:查询每个部门每个工种的员工的平均工资,并按平均工资的高低显示
SELECT AVG(salary),department_id,job_id FROM employees WHERE department_id IS NOT NULL GROUP BY department_id,job_id HAVING AVG(salary)>10000 ORDER BY AVG(salary) DESC;