学习MySQL、03数据库的高级查询(面试常问!)

3 篇文章 0 订阅
2 篇文章 0 订阅

标题目录

1、学习目标
2、聚合函数的使用
3、分组查询
4、HAVING子句
5、表的内连接
6、表的外连接

标题1、学习目标

查询可以做到如:求最大值最小值、平均值

1、数据统计分析,涉及聚合函数、分组查询、HAVING子句

2、多表连接,涉及内连接、外连接,以及多表查询的多种语法

3、子查询(再查询结果中嵌套一个查询),涉及单行子查询,多行子查询,WHERE子查询,FROM子查询、SELECT子查询

标题2、聚合函数

在数据的查询分析中,应用十分广泛。可以求最大值最小值、平均值等等。

如求公司员工平均月收入

SELECT AVG(sal+IFNULL(comm,0)) FROM t_emp;

几个函数:SUM()、MAX()、MIN()、AVG()、COUNT()

MAX():用于获得非空值的最大值

SELECT MAX(sal+IFNULL(comm,0)) FROM t_emp WHERE deptno IN(10,20);

MIN():用于获得非空值的最小值

SELECT MIN(hiredate) FROM t_emp;

AVG():用于获得非空值的平均值,非数字数据统计结果为0

COUNT():COUNT(*)获得包含空值的记录数,CPUNT(列名)用于获得包含非空值的记录数

如查询10和20部门中,底薪超过2000元并且工龄超过15的员工人数

SELECT COUNT(*) FROM t_emp
WHERE deptno IN(10,20) AND sal>=2000
AND DATEIFF(NOW(),hiredate)/365>=15;

查询1985年以后入职的员工,底薪超过公司平均底薪的员工数量

错误例子如下:

SELECT FROM t_emp
WHERE hiredate>="1985-01-01"
AND sal>AVG(sal);#错误

注意:聚合函数是永远不能出现在WHERE字句中的。比如说上例,因为where都没有划定数据筛选的范围,就用条件去判断sal>AVG(sal)是错的

标题3、分组查询

3.1 为什么要分组呢?

因为默认情况下汇总函数是对全表范围内的数据做统计

GROUP BY子句的作用是通过一定的规则讲一个数据集划分成若干个小的取与,然后针对每个小区域分别做数据汇总处理,如

SELECT deptno,AVG(sal) FROM t_emp GROUP BY deptno;

3.2 逐级分组

数据库支持多列分组条件,执行的时候逐级分组

查询每个部门里,每种职位的人员数量和平均底薪

SELECT deptno,job,COUNT(*),AVG(sal) FROM t_emp 
GROUP BY deptno,job
ORDER BY deptno;

3.3 对分组结果集再次做汇总计算

SELECT deptno,COUNT(*),AVG(sal),MAX(sal),MIN(sal) 
FROM t_emp
GROUP BY deptno
WITH ROLLUP;

查询结果为
在这里插入图片描述

3.4 GROUP_CONCAT()函数

SELECT deptno,COUNT(*),GROUP_CONCATT(ename)
FROM t_emp
WHERE sal>=200
GROUP BY deptno

查询结果为
在这里插入图片描述

标题4.HAVING子句

为什么引入HAVING子句?

分组查询时候有时候会遇到困难,如查询部门平均底薪超过2000元的部门编号,逻辑上是这样写,但是是一定会报错的,

SELECT deptno FROM t_emp
WHERE AVG(sal)>=2000
GROUP BY deptno;

原因在于WHERE的优先级是高于GROUP BY的,WHERE子句中出现了汇总函数AVG(), GROUP BY执行之前,MYSQL不知道按照怎么样的统计规则去汇总这个数据,所以语法上就是有错误的。正确的思路是讲AVG()这个汇总的函数从WHERE子句里面抽出来。

HAVING子句是在GROUP BY后面,不能单独出现。

SELECT deptno FROM t_emp
GROUP BY deptno HAVING  AVG(sal)>=2000;

查询每个部门中,1982年以后入职的员工超过2个人的部门编号

SELECT FROM t_emp
WHERE hiredate>="1982-01-01"
GROUP BY deptno HAVING COUNT(*)>=2
ORDER BY deptno ASC;

注意:在HAVING子句里面的规则和在WHERE子句里面规则是一样的,聚合函数不能和某一个字段去比较,比如sal>=AVG(sal)是不行的。解决这个问题要引入表连接。
在这里插入图片描述

标题5、表的内连接

在这里插入图片描述

5.1 表连接的分类
内连接是结果集只保留符合链接条件的记录

外连接是不管符不符合连接条件,记录都要保留在结果集中

内连接
在这里插入图片描述
在这里插入图片描述

案例演示:

#查询每个员工的工号、姓名、部门名称、底薪、职位、工资等级
SELECT e.empno,e.ename,d.dname,
FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno 
JOIN t_salgrade s ON e.sal BETWEEN s.losal AND s.hisal;

从这个例子可以看出,内连接的数据表不一定必须有同名字段,只要字段之间符合逻辑关系就可以。

这种嵌套查询的方式效率比较低下,如下图

在这里插入图片描述

一个技巧:表跟自己做表链接,也就是说相同的表也可以做表连接。

在这里插入图片描述

这样子的查询速度就会快很多很多

标题6、表的外连接

因为我们一开始的连接条件是部门表的部门编号和员工表的部门标号相同,而陈浩这个人没有部门编号,所以做内连接的时候就会漏掉
在这里插入图片描述

外连接案例演示:

SELECT e.empno,e.ename,d.dname 
FROM t_emp e LEFT JOIN t_dept d ON e.deptno = d.deptno

LEFT JOIN 就是保留左表的记录然后和右表做连接,加入说员工表中陈浩这条记录没有部门编号,那么想要在结果集中显示出陈浩,就需要拿t_emp做左表,进行左外连接。右外连接同理。

练习题:(待更新)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值