一、单元概述
通过本章的学习能够理解MySQL数据库中分组查询的含义,掌握常用分组函数的使用,掌握GROUP BY子句的使用规则,掌握分组后数据结果的条件过滤,掌握SELECT语句执行过程,理解子查询的含义,掌握单行子查询和多行子查询的使用
二、教学重点与难点
重点:
掌握常用分组函数的使用
掌握GROUP BY子句的使用规则
掌握HAVING子句的使用规则
掌握子查询的使用规则
难点:
SELECT语句执行过程
HAVING和WHERE的区别
单行子查询和多行子查询
请思考如下问题?
分组函数是对数据行的集合进行操作并按组给出一个结果,这个结果可直接输出,或者用来做判断条件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nQjKPrFg-1596085819799)(images/图片7-1.png)]
SELECT [column,] group_function(column)
FROM table
[WHERE condition]
[GROUP BY column]
[HAVING group_function(column)expression
[ORDER BY column | group_function(column)expression];
SELECT MIN(hiredate), MAX(hiredate)
FROM emp;
MIN(HIRED | MAX(HIRED |
---|---|
1980-12-17 | 1987-05-23 |
SELECT AVG(sal), MAX(sal),MIN(sal), SUM(sal)
FROM emp
WHERE job LIKE 'SALES%';
AVG(SAL) | MAX(SAL) | MIN(SAL) | SUM(SAL) |
---|---|---|---|
1400 | 1600 | 1250 | 5600 |
COUNT函数的主要功能是返回满足条件的每组记录条数。
COUNT( * | {[DISTINCT | ALL] column | expression})
COUNT(*):返回表中满足条件的行记录数
查询部门30有多少个员工
SELECT COUNT(*)
FROM emp
WHERE deptno = 30;
COUNT(*) |
---|
6 |
SELECT COUNT(comm)
FROM emp
WHERE deptno = 30;
COUNT(COMM) |
---|
4 |
SELECT COUNT(DISTINCT deptno)
FROM emp;
SELECT AVG(comm)
FROM emp;
AVG(COMM) |
---|
550 |
SELECT AVG(IFNULL(comm,0))
FROM emp;
AVG(IFNULL(COMM,0)) |
---|
157.14286 |
练习
通过 GROUP BY 子句可将表中满足WHERE条件的记录按照指定的列划分成若干个小组
SELECT column, group_function(column)
FROM table
[WHERE condition]
[GROUP BY group_by_expression]
[ORDER BY column];
SELECT deptno, AVG(sal)
FROM emp
GROUP BY deptno;
DEPTNO | AVG(SAL) |
---|---|
10 | 2916.6667 |
20 | 2175 |
30 | 1566.6667 |
SELECT deptno, AVG(sal)
FROM emp
GROUP BY deptno;
DEPTNO | AVG(SAL) |
---|---|
10 | 2916.6667 |
20 | 2175 |
30 | 1566.6667 |
SELECT AVG(sal)
FROM emp
GROUP BY deptno;
AVG(SAL) |
---|
2916.6667 |
2175 |
1566.6667 |
查询每个部门每个岗位的工资总和。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-edtXNGZB-1596085819804)(images/图片7-3.png)]
查询每个部门每个岗位的工资总和
SELECT deptno, job, sum(sal)
FROM emp
GROUP BY deptno, job;
DEPTNO | JOB | SUM(SAL) |
---|---|---|
10 | CLERK | 1300 |
10 | MANAGER | 2450 |
10 | PRESIDENT | 5000 |
20 | ANALYST | 6000 |
20 | CLERK | 1900 |
… |
练习
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iABaDbal-1596085819806)(images/图片7-5.png)]
SELECT deptno, max(sal)
FROM emp
WHERE max(sal) > 2900
GROUP BY deptno;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4J09oTDE-1596085819809)(images/图片7-4.png)]
使用 HAVING 子句限制组
SELECT column, group_function
FROM table
[WHERE condition]
[GROUP BY group_by_expression]
[HAVING group_condition]
[ORDER BY column];
SELECT deptno, max(sal)
FROM emp
GROUP BY deptno
HAVING max(sal)>2900;
DEPTNO | MAX(SAL) |
---|---|
10 | 5000 |
20 | 3000 |
SELECT job, SUM(sal) PAYROLL
FROM emp
WHERE job NOT LIKE 'SALES%'
GROUP BY job
HAVING SUM(sal)>5000
ORDER BY SUM(sal);
JOB | PAYROLL |
---|---|
ANALYST | 6000 |
MANAGER | 8275 |
SELECT deptno,job,avg(sal)
FROM emp
WHERE job in ('SALESMAN','MANAGER','CLERK')
GROUP BY deptno,job
HAVING avg(sal)>1000
ORDER BY 3 DESC;
DEPTNO | JOB | AVG(SAL) |
---|---|---|
20 | MANAGER | 2975 |
30 | MANAGER | 2850 |
10 | MANAGER | 2450 |
30 | SALESMAN | 1400 |
10 | CLERK | 1300 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xeXd4SFT-1596085819812)(images/图片7-6.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MS2nXv8o-1596085819814)(images/图片7-7.png)]
练习
思考如下问题?
“谁的薪水比 Jones还高呢?”
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zenb0ahA-1596085819815)(images/图片4-3.png)]
子查询语法
SELECT select_list
FROM table
WHERE expr operator
(SELECT select_list
FROM table);
括号内的查询叫做子查询,也叫内部查询,先于主查询执行。
子查询的结果被主查询(外部查询)使用
expr operator包括比较运算符
子查询可以嵌于以下SQL子句中:
SELECT ename
FROM emp
WHERE sal >
(SELECT sal
FROM emp
WHERE ename='JONES');
ENAME |
---|
KING |
FORD |
SCOTT |
根据子查询返回的行和列数量,分为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WINedkPY-1596085819816)(images/图片4-4.png)]
SELECT ename, job
FROM emp
WHERE job =
(SELECT job FROM emp WHERE empno = 7369)
AND sal >
(SELECT sal FROM emp WHERE empno = 7876);
ENAME | JOB |
---|---|
MILLER | CLERK |
SELECT ename, job, sal
FROM emp
WHERE sal =
(SELECT MIN(sal) FROM emp);
ENAME | JOB | SAL |
---|---|---|
SMITH | CLERK | 800 |
SELECT deptno, MIN(sal)
FROM emp
GROUP BY deptno
HAVING MIN(sal) >
(SELECT MIN(sal)
FROM emp
WHERE deptno = 20);
练习
子查询返回记录的条数 可以是一条或多条。
和多行子查询进行比较时,需要使用多行操作符,多行操作符包括:
IN操作符和以前介绍的功能一致,判断是否与子查询的任意一个返回值相同。
SELECT ename, sal
FROM emp
WHERE empno IN (SELECT mgr
FROM emp);
ENAME | SAL |
---|---|
SCOTT | 3000.00 |
KING | 5000.00 |
JONES | 2975.00 |
FORD | 3000.00 |
CLARK | 2450.00 |
BLAKE | 2850.00 |
ANY:表示和子查询的任意一行结果进行比较,有一个满足条件即可。
案例1 查询是经理的员工姓名,工资。
SELECT ename, sal
FROM emp
WHERE empno = ANY (SELECT mgr
FROM emp);
ENAME | SAL |
---|---|
JONES | 2975.00 |
BLAKE | 2850.00 |
CLARK | 2450.00 |
SCOTT | 3000.00 |
KING | 5000.00 |
FORD | 3000.00 |
SELECT empno, ename, job, sal
FROM emp
WHERE sal > ANY (SELECT sal
FROM emp
WHERE deptno = 10)
AND deptno <> 10;
| EMPNO | ENAME | JOB | SAL |
| 7499 | ALLEN | SALESMAN | 1600.00 |
| 7566 | JONES | MANAGER | 2975.00 |
| 7698 | BLAKE | MANAGER | 2850.00 |
| 7788 | SCOTT | ANALYST | 3000.00 |
| 7844 | TURNER | SALESMAN | 1500.00 |
| 7902 | FORD | ANALYST | 3000.00 |
ALL:表示和子查询的所有行结果进行比较,每一行必须都满足条件。
案例1 查询部门编号不为20,且工资比20部门所有员工工资高的员工编号,姓名,职位,工资。
SELECT empno, ename,job, sal
FROM emp
WHERE sal > ALL (SELECT sal
FROM emp
WHERE deptno= 20)
AND deptno <> 20;
EMPNO | ENAME | JOB | SAL |
---|---|---|---|
7839 | KING | PRESIDENT | 5000.00 |
SELECT empno, ename,job, sal
FROM emp
WHERE sal < ALL (SELECT sal
FROM emp
WHERE deptno= 10)
AND deptno <> 10;
EMPNO | ENAME | JOB | SAL |
---|---|---|---|
7369 | SMITH | CLERK | 800.00 |
7521 | WARD | SALESMAN | 1250.00 |
7654 | MARTIN | SALESMAN | 1250.00 |
7876 | ADAMS | CLERK | 1100.00 |
7900 | JAMES | CLERK | 950.00 |
练习
SELECT ename
FROM emp
WHERE empno NOT IN
(SELECT mgr
FROM emp);
ENAME |
---|
SELECT a.ename, a.sal, a.deptno, b.salavg
FROM emp a, (SELECT deptno, AVG(sal) salavg
FROM emp
GROUP BY deptno) b
WHERE a.deptno = b.deptno AND a.sal > b.salavg;
ename | sal | deptno | salavg |
---|---|---|---|
KING | 5000.00 | 10 | 2916.666667 |
JONES | 2975.00 | 20 | 2175.000000 |
SCOTT | 3000.00 | 20 | 2175.000000 |
FORD | 3000.00 | 20 | 2175.000000 |
ALLEN | 1600.00 | 30 | 1566.666667 |
BLAKE | 2850.00 | 30 | 1566.666667 |
本章小结
本章作业
1.查询部门平均工资在2500元以上的部门名称及平均工资。
2.查询员工岗位中不是以“SA”开头并且平均工资在2500元以上的岗位及平均工资,并按平均工资降序排序。
3.查询部门人数在2人以上的部门名称、最低工资、最高工资。
4.查询岗位不为SALESMAN,工资和大于等于2500的岗位及每种岗位的工资和。
5.显示经理号码和经理姓名,这个经理所管理员工的最低工资,没有经理的KING也要显示,不包括最低工资小于3000的,按最低工资由高到低排序
6.查询工资高于编号为7782的员工工资,并且和7369号员工从事相同工作的员工的编号、姓名及工资。
7.查询工资最高的员工姓名和工资。
8.查询部门最低工资高于10号部门最低工资的部门的编号、名称及部门最低工资。
9.查询员工工资为其部门最低工资的员工的编号和姓名及工资。
10.显示经理是KING的员工姓名,工资。
11.显示比员工SMITH参加工作时间晚的员工姓名,工资,参加工作时间。