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()返回查询到的数据的最小值,不是数字没有意义

特点:

  1. sum() , avg()一般用于处理数值
  2. max() , min() , count()可以处理任何类型。
  3. 以上分组函数都会自动过滤null。
  4. 可以实现与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