MySQL学习-group by和having

操作的表
mysql> select * from emp;

EMPNOENAMEJOBMGRHIREDATESALCOMMDEPTNO
7369SMITHCLERK79021980-12-17800.00NULL20
7499ALLENSALESMAN76981981-02-201600.00300.0030
7521WARDSALESMAN76981981-02-221250.00500.0030
7566JONESMANAGER78391981-04-022975.00NULL20
7654MARTINSALESMAN76981981-09-281250.001400.0030
7698BLAKEMANAGER78391981-05-012850.00NULL30
7782CLARKMANAGER78391981-06-092450.00NULL10
7788SCOTTANALYST75661987-04-193000.00NULL20
7839KINGPRESIDENTNULL1981-11-175000.00NULL10
7844TURNERSALESMAN76981981-09-081500.000.0030
7876ADAMSCLERK77881987-05-231100.00NULL20
7900JAMESCLERK76981981-12-03950.00NULL30
7902FORDANALYST75661981-12-033000.00NULL20
7934MILLERCLERK77821982-01-231300.00NULL10

group by

group by : 按照某个字段或者某些字段进行分组。
having : having是对分组之后的数据进行再次过滤。
案例:找出每个工作岗位的最高薪资。

(找的是每一组的最高薪资,所以需要先进行分组)
    select job,max(sal) from emp group by job;

+-----------+----------+
| job       | max(sal) |
+-----------+----------+
| ANALYST   |  3000.00 |
| CLERK     |  1300.00 |
| MANAGER   |  2975.00 |
| PRESIDENT |  5000.00 |
| SALESMAN  |  1600.00 |
+-----------+----------+

先from,再group by,最后求max
分组函数总是在group函数结束之后再执行
注意:分组函数一般都会和group by联合使用,这也是为什么它被称为分组函数的原因。
并且任何一个分组函数(count sum avg max min)都是在group by语句执行结束之后才会执行的

当一条sql语句没有group by的话,整张表的数据会自成一组。

多字段分组查询

找出每个工作岗位的最高薪资
    select ename,job,max(sal) from emp group by job;
这条语句能不能执行,Oracle不能,MySQL可以,但没意义

+-------+-----------+----------+
| ename | job       | max(sal) |
+-------+-----------+----------+
| SCOTT | ANALYST   |  3000.00 |
| SMITH | CLERK     |  1300.00 |
| JONES | MANAGER   |  2975.00 |
| KING  | PRESIDENT |  5000.00 |
| ALLEN | SALESMAN  |  1600.00 |
+-------+-----------+----------+

以上在mysql当中,查询结果是有的,但是结果没有意义,在Oracle数据库当中会报错。语法错误。
Oracle的语法规则比MySQL语法规则严谨。
记住一个规则:当一条语句中有group by的话,select后面只能跟分组函数和参与分组的字段。
每个工作岗位的平均薪资?
    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 deptno,job,sal from emp order by deptno;

+--------+-----------+---------+
| deptno | job       | sal     |
+--------+-----------+---------+
|     10 | MANAGER   | 2450.00 |
|     10 | PRESIDENT | 5000.00 |
|     10 | CLERK     | 1300.00 |
|     20 | CLERK     |  800.00 |
|     20 | MANAGER   | 2975.00 |
|     20 | ANALYST   | 3000.00 |
|     20 | CLERK     | 1100.00 |
|     20 | ANALYST   | 3000.00 |
|     30 | SALESMAN  | 1600.00 |
|     30 | SALESMAN  | 1250.00 |
|     30 | SALESMAN  | 1250.00 |
|     30 | MANAGER   | 2850.00 |
|     30 | SALESMAN  | 1500.00 |
|     30 | CLERK     |  950.00 |
+--------+-----------+---------+
		select 
			deptno,job,max(sal)
		from
			emp
		group by
			deptno,job;

where和having的选择
找出每个部门的最高薪资,要求显示薪资大于2900的数据。

写SQL语句的时候,有时别幻想着一步就能写出来,有时候读一句,写一句。要分步骤来写。
第一步:找出每个部门的最高薪资
    select max(sal),deptno from emp group by deptno;

+----------+--------+
| max(sal) | deptno |
+----------+--------+
|  5000.00 |     10 |
|  3000.00 |     20 |
|  2850.00 |     30 |
+----------+--------+

第二步:找出薪资大于2900
    select max(sal),deptno from emp group by deptno having max(sal) > 2900; // 这种方式效率低。因为第一次结果就已经查出来了,还要计算分组函数

+----------+--------+
| max(sal) | deptno |
+----------+--------+
|  5000.00 |     10 |
|  3000.00 |     20 |
+----------+--------+

    select max(sal),deptno from emp where sal > 2900 group by deptno; // 效率较高,建议能够使用where过滤的尽量使用where。
where已经提前过滤了。
where搞不定的我们就用having

找出每个部门的平均薪资,要求显示薪资大于2000的数据。
第一步:找出每个部门的平均薪资
    select deptno,avg(sal) from emp group by deptno;
第二步:要求显示薪资大于2000的数据
    select avg(sal),deptno from emp group by deptno having avg(sal)>2000;

+--------+-------------+
| deptno | avg(sal)    |
+--------+-------------+
|     10 | 2916.666667 |
|     20 | 2175.000000 |
+--------+-------------+

where后面不能使用分组函数:
    select deptno,avg(sal) from emp where avg(sal) > 2000 group by deptno; // 错误了。
这种情况只能使用having过滤。
having是groupby的搭档,只有groupby出现了,having才有意义

总结一个完整的DQL语句怎么写?

    select			5
		..
	from			1	
		..
	where			2
		..
	group by		3
		..
	having			4
		..
	order by		6

排序是最后的,排序最后输出。

去除重复记录

1、关于查询结果集的去重?

    select DISTINCT job from emp; // distinct关键字去除重复记录。

+-----------+
| job       |
+-----------+
| CLERK     |
| SALESMAN  |
| MANAGER   |
| ANALYST   |
| PRESIDENT |
+-----------+

mysql> select ename,distinct job from emp;
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘distinct job from emp’ at line 1
以上的sql语句是错误的。
记住:distinct只能出现在所有字段的最前面。

    select distinct deptno,job from emp;

+--------+-----------+
| deptno | job       |
+--------+-----------+
|     20 | CLERK     |
|     30 | SALESMAN  |
|     20 | MANAGER   |
|     30 | MANAGER   |
|     10 | MANAGER   |
|     20 | ANALYST   |
|     10 | PRESIDENT |
|     30 | CLERK     |
|     10 | CLERK     |
+--------+-----------+

distinct放到最前面表示后面所有字段去除重复记录。这里表名去除deptno和job同时重复的去掉
案例:统计岗位的数量?
   select count(distinct job) from emp;
去重之后统计数量

+---------------------+
| count(distinct job) |
+---------------------+
|                   5 |
+---------------------+
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值