单行处理函数
什么是单行处理函数?
输入一行,输出一行
计算每个员工的年薪?
select ename,(sal+com)*12 as yearsal from emp;
+--------+----------+
| ename | yearsal |
+--------+----------+
| SMITH | NULL |
| ALLEN | 22800.00 |
| WARD | 21000.00 |
| JONES | NULL |
| MARTIN | 31800.00 |
| BLAKE | NULL |
| CLARK | NULL |
| SCOTT | NULL |
| KING | NULL |
| TURNER | 18000.00 |
| ADAMS | NULL |
| JAMES | NULL |
| FORD | NULL |
| MILLER | NULL |
+--------+----------+ 会发现有空年薪的情况存在,因为有员工补助是为空的
remember:数据库中 无论是MySQL,Orcale 只要有和NULL进行运算那么结果也为NULL
ifnull() 空处理函数?
ifnull(可能为NULL的数据,被当作什么看)
重写之前那句:
select ename,(sal+ifnull(com,0))*12 as yearsal from emp;
+--------+----------+
| ename | yearsal | ifnull(comm,0) 如果comm为null ,则将其等效为0
+--------+----------+
| SMITH | 9600.00 |
| ALLEN | 22800.00 |
| WARD | 21000.00 |
| JONES | 35700.00 |
| MARTIN | 31800.00 |
| BLAKE | 34200.00 |
| CLARK | 29400.00 |
| SCOTT | 36000.00 |
| KING | 60000.00 |
| TURNER | 18000.00 |
| ADAMS | 13200.00 |
| JAMES | 11400.00 |
| FORD | 36000.00 |
| MILLER | 15600.00 |
+--------+----------+
分组函数一共5个
分组函数还有另一个名字:多行处理函数
多行处理函数的特点:输入多行,最终输出结果为1行
count计数
sum 求和
avg 求平均
max 最大值
min 最小值
remember:所有的分组函数都是对“某一组”数据进行操作的。
找出工资总和?
select sum(sal) from emp;
找出最高工资?
select max(sal) from emp;
找出最低工资?
select min(sal) from emp;
找出平均工资
select avg(sal) from emp;
找出总人数?
select count(*) from emp;
分组函数自动忽略NULL
select count(comm) from emp;
+-------------+
| count(comm) |
+-------------+
| 4 |
+-------------+
select sum(comm) from emp;
+-----------+
| sum(comm) |
+-----------+
| 2200.00 |
+-----------+
对比单行处理函数,可以看到多行处理函数里忽略掉了null(重要)
找出工资高于平均工资的员工
select avg(sal) from emp;//平均工资
首先可能会想到这样写,select ename,sal from emp where sal>avg(sal); //但是会报错
//err:ERROR 1111 (HY000): Invalid use of group function 无效的使用了分组函数
原因:SQL语句当中有一个语法规则,分组函数不可直接使用在where字句中。(讲完group by 可以知晓), group by是在where执行之后才会执行的,同时分组函数要在分组(group by)之后再执行。
select 5
from 1
where 2
group by 3
having 4
order by 6
解决:找出高于平均工资的员工
第一步:找出平均工资
select avg(sal) from emp;
+-------------+
| avg(sal) |
+-------------+
| 2073.214286 |
+-------------+
第二部:找出高于平均工资的员工
+-------+---------+
| ename | sal |
+-------+---------+
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
| FORD | 3000.00 |
+-------+---------+
将两步合为一步
select ename,sal from emp where sal>(select avg(sal) from emp); //子查询,嵌套
本部分重点为where后面不能跟分组函数
count(*)和count(某个字段)区别
count(*):不是统计某个字段中数据的个数,而是统计总记录条数。(和某个字段无关)
count(某个字段):表示统计comm字段中不为NULL数据总数量
分组函数也能组合起来用:
select count(*),sum(sal),avg(sal),max(sal),min(sal) from emp;
+----------+----------+-------------+----------+----------+
| count(*) | sum(sal) | avg(sal) | max(sal) | min(sal) |
+----------+----------+-------------+----------+----------+
| 14 | 29025.00 | 2073.214286 | 5000.00 | 800.00 |
+----------+----------+-------------+----------+----------+
16.goup by 和 having
group by:按照某个字段或者某些字段进行分组
having:having是对分组之后的数据进行再次过滤
案例:找出每个工作岗位的最高薪资。
select max(sal) from emp group by job; //这个是先执行group by(即先用job分组),在执行前面的筛查
注意:分组函数一般都会和group by 联合使用,这也是为什么它称为分组函数的原因。
并且任何一个分组函数(count sum avg max min)都是在group by 语句执行结束之后才会执行的。
当一条sql语句没有group by的话,整张表的数据会自成一组
+-----------+----------+
| job | max(sal) |
+-----------+----------+
| ANALYST | 3000.00 |
| CLERK | 1300.00 |
| MANAGER | 2975.00 |
| PRESIDENT | 5000.00 |
| SALESMAN | 1600.00 |
+-----------+----------+
当一条语句有group by的时候,select后面只能跟参加分组的字段以及分组函数。跟其他无关字段会报错,在MySQL中即使能够通过但是没有意义
que:每个岗位的平均工资
select job,avg(sal) from emp group by job;
+-----------+-------------+
| job | avg(sal) |
+-----------+-------------+
| ANALYST | 3000.000000 |
| CLERK | 1037.500000 |
| MANAGER | 2758.333333 |
| PRESIDENT | 5000.000000 |
| SALESMAN | 1400.000000 |
+-----------+-------------+
多个字段能不能联合起来一块分组?
案例:找出每个部门不同工作岗位的最高薪资。
select
max(sal),job,deptno
from emp
group by
job,deptno;
+----------+-----------+--------+
| max(sal) | job | deptno |
+----------+-----------+--------+
| 3000.00 | ANALYST | 20 |
| 1300.00 | CLERK | 10 |
| 1100.00 | CLERK | 20 |
| 950.00 | CLERK | 30 |
| 2450.00 | MANAGER | 10 |
| 2975.00 | MANAGER | 20 |
| 2850.00 | MANAGER | 30 |
| 5000.00 | PRESIDENT | 10 |
| 1600.00 | SALESMAN | 30 |
+----------+-----------+--------+
找出每个部门的最高薪资,要求显示薪资大于2900的数据。
第一步:找到每个部门的最高薪资.
mysql> select max(sal),deptno from emp group by deptno;
+----------+--------+
| max(sal) | deptno |
+----------+--------+
| 5000.00 | 10 |
| 3000.00 | 20 |
| 2850.00 | 30 |
+----------+--------+
第二步:找出薪资大于2900(加having过滤) //这种方式效率低
select max(sal),deptno from emp group by deptno having max(sal)>2900;
这里为了提高效率 建议先用where
select max(sal),deptno from emp where sal >2900 group by deptno;
假设一个用where无法判断的情况
找出每个部门的平均薪资,要求显示薪资大于2900的数据?
第一步找到部门平均工资
select avg(sal),deptno from emp group by deptno;
+-------------+--------+
| avg(sal) | deptno |
+-------------+--------+
| 2916.666667 | 10 |
| 2175.000000 | 20 |
| 1566.666667 | 30 |
+-------------+--------+
第一步找到部门平均工资这种情况就必须要使用having进行区分
关于查询结果去重?
select distinct job from emp; //distinct 关键字去除重复记录
select ename , distinct job from emp;
以上的sql语句是错误的
remember:distinct 只能出现在所有字段的最前面
select distinct deptno,job from emp;//distinct是所有后面字段联合起来去重
统计岗位数量?
select count(distinct job) from emp;//去除重复的岗位后再进行计数
总结一个完整的DQL语句怎么写?
select 5
..
from 1
..
where 2
..
group by 3
..
having 4
..
order by 6
..