group by 和 having 是搭档
group by : 按照某一个字段或则某些字段进行分组,一般和分组函数一起使用,不然表会自成一组。
having : having是对分区后的数据进行再次过滤,需要有group by搭配使用,如果where 可以满足的话尽量使用where 条件判断。
order by 和 group by 的区别:
1,order by 从英文里理解就是行的排序方式,默认的为升序。 order by 后面必须列出排序的字段名,可以是多个字段名。
2,group by 从英文里理解就是分组。必须有“聚合函数”来配合才能使用,使用时至少需要一个分组标志字段。
注意:聚合函数是---sum()、count()、avg()等都是“聚合函数”
案例:找出每个工作岗位的最高工资?
select max(sal) from emp group by job;
注意:分组函数一般都会和group by联合使用,这也还为什么他称为分组函数的原因。
并且任何一个分组函数(count,sum,max,min,avg)都是在 group by 语句执行结果之后才会被执行。
当一条sql 语句没有group by 的话,整张表的数据会成一组。
当一条语句有group by 的话,select只允许出现参与分组字段、分组函数。其他字段不能写,执行后 mysql 出数据没有任意意义,在oracle执行数据库会报错,oracle的语法规则比mysql 语法规则严谨。
作用:用作统计使用,又称为聚合函数或者统计函数或者组函数。
多行处理函数特点:输入多行,最终输出一个结果
分组函数自动忽略NULL
分组函数不能添加在where后面,group by 语句是在where 之后至此那个,正确的书写:
select ename,sal from emp where sal > (select avg(sal) from emp);
count(*): 不是统计某个字段中的个数,而是统计总记录条数。(和摸一个字段无关)
count(comm) :表示统计comm字段中不为NULL的数据总数量
执行顺序
执行 | 执行顺序 | |
---|---|---|
select ... | 5 | 执行select 选出数据 |
from ... | 1 | |
where ... | 2 | 执行wher语句过滤原始数据 |
group by ... | 3 | 执行group by 进行分组 |
having ... | 4 | 执行having 对分组数据进行操作 |
order by ... | 6 | 执行order by 排序 |
原则:能在where中过滤数据,尽量在where中过滤,效率较高。having的过滤是专门对分组之后的数据进行过滤,where后面不能使用分组函数,可以使用having。
单行处理函数
什么是单行处理函数?
输入一行,输出一行
计算每个员工的年薪?
select ename,(sal+comm)*12 as yearsal from emp; // 错误的写法
正确的方式: ifnull(可能为NULL的数据,被当成什么处理),可以
select ename,(sal+ifnull(comm,0))*12 as yearsal from emp;
输入多行,最终输出也是多行
分组函数:
聚合函数
函数 | 说明 |
---|---|
count() | 返回查询数据的数量 |
sum() | 返回查询到的数据的总和,不是数字没有意义 |
avg() | 返回查询到的数据的平均值,不是数字没有意义 |
max() | 返回查询到的数据的最大值,不是数字没有意义 |
min() | 返回查询到的数据的最小值,不是数字没有意义 |
特点:
- sum() , avg()一般用于处理数值
- max() , min() , count()可以处理任何类型。
- 以上分组函数都会自动过滤null。
- 可以实现与distinct组合使用。
例子:
--sum() 求和
select sum(salary) from employees;
--avg() 求平均值
select avg(salary) from employees;
--max() 求最大值
select max(salary) from employees;
--min() 求最小值
select min(salary) from employees;
--count() 计算个数
select count(commission_pct) from employees;
分组查询:
语法:
select 查询列表 from 表 【where 筛选条件】 group by 分组字段 【order by】 【having 条件】
特点:
1、和分组函数一同查询的字段必须是group by后出现的字段
2、筛选分为两类:分组前筛选和分组后筛选
3、分组可以按单个字段也可以按多个字段
4、可以搭配着排序使用
分组前筛选原始表 group by前where
分组后筛选group by后的结果集 group by后having
问题1:分组函数做筛选能不能放在where后面答:不能
问题2: where- droup by- having
一般来讲,能用分组前筛选的,尽量使用分组前筛选,提高效率
例题:
--查询将每个工种的员工的平均工资
select job_id,avg(salary) from employees GROUP BY job_id;
--查询邮箱中包含a字符的,每个部门的最高工资。
select department_id,MAX(salary) from employees where email like '%a%' GROUP BY department_id;
--查询有奖金的每个领导手下员工的平均工资。
select manager_id,AVG(salary) from employees where commission_pct is not null GROUP BY manager_id;
--查询员工表中的最大入职时间和最小入职时间的相差天数 ( TO_DAYS() 将日期时间转换成天数)
select TO_DAYS(MAX(hiredate))-TO_DAYS(MIN(hiredate)) from employees;
select DATEDIFF(MAX(hiredate),MIN(hiredate)) from employees; ( DATEDIFF() 计算两段时间的天数 )
--查询部门编号为90的员工个数
select department_id,COUNT(employee_id) FROM employees where department_id = 90 GROUP BY department_id;
--查询公司员工工资的最大值,最小值,平均值,总和
select MAX(salary),MIN(salary),AVG(salary),SUM(salary) from employees;
--查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资。
select job_id,MAX(salary) from employees where commission_pct is not null GROUP BY job_id HAVING MAX(salary)>12000;
----查询每个工种有奖金的员工的最高工资>6000的工种编号和最高工资, 按照最高工资升序。
select job_id,MAX(salary) from employees where commission_pct is not null GROUP BY job_id HAVING MAX(salary)>6000 ORDER BY MAX(salary) DESC;
--查询每个工种每个部门的最低工资,并按最低工资降序
select job_id,department_id,min(salary) from employees GROUP BY job_id,department_id ORDER BY MAX(salary) DESC;
--查询各job_id的员工工资的最大值,最小值,平均值,总和,并按job_id升序
select MAX(salary),MIN(salary),AVG(salary),COUNT(salary) from employees GROUP BY job_id ORDER BY job_id;
--查询员工最高工资和最低工资的差距(DIFFERENCE)
select MAX(salary)-MIN(salary) DIFFERENCE from employees;
拓展:
count()的效率
SHOW ENGINES; --显示所有储存引擎
select count(1) from employees;
select count(*) from employees;
效率:
MYISAM储存引擎下,count()的效率高
INNODB储存引擎下,count()和count(1)的效率差不多
作业:
--1.查询部门编号为90的员工个数
select department_id,count(1) from employees where department_id = 90 ORDER BY department_id;
--2.领导编号>102的每个领导手下的最低工资大于5000的领导编号和最低工资
select manager_id,min(salary) from employees where manager_id>102 GROUP BY manager_id HAVING MIN(salary)>5000;
--3.选择工资不在8000到17000的员工的姓名和工资,按工资降序
select last_name,salary from employees where salary not BETWEEN 8000 and 17000 ORDER BY salary desc;
--4.选择具有各个job_id的员工人数
select job_id,count(1) from employees group by job_id;
--5.查询各个管理者手下员工的最低工资,其中最低工资不能低于6000,没有管理者的员工不计算在内
select manager_id,min(salary) from employees where manager_id is not null group by manager_id having min(salary)>=6000;
--6.查询各job_id的员工工资的最大值,最小值,平均值,总和,并按job_id升序
select job_id,max(salary),min(salary),avg(salary),sum(salary) from employees group