Java工程师-15-16周MySQL基础-第四章(数据库的高级查询)

62 阅读3分钟

第四章 数据库的高级查询

image.png

4.1 聚合函数

聚合函数是用于简单的统计的

image.png

image.png

一般只用sum函数求数字类型的和

image.png

image.png

image.png

image.png

4.2 分组查询

image.png

image.png

image.png

只能出现deptno以及使用的聚合函数,sal是一个单独的字段,所以不可以

image.png

image.png

image.png

注意:这里where子句要在分组语句之前,找到符合条件的数据之后再进行分组

image.png

4.3 Having子句

image.png

where子句中不能出现聚合函数,要使用having子句

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

image.png

注意:HAVING子句中和某个数值比可以,但是不能和某个字段进行比较,要进行表连接

4.4 表连接

image.png

image.png

image.png

4.4.1 内连接

image.png

image.png

  • 连接条件写在where子句中
  • JOIN可以使用逗号替代

image.png

SELECT
	e.empno, e.ename, d.deptno, e.sal, e.job, s.grade
FROM 
	t_emp e, t_dept d, t_salgrade s 
WHERE 
	e.deptno = d.deptno AND e.sal BETWEEN s.losal AND s.hisal; 

image.png

使用子查询实现:

SELECT 
FROM t_emp
WHERE deptno=(SELECT deptno FROM t_emp WHERE ename="SCOTT") AND ename != 'SCOTT';

数据库在执行子查询的时候是非常慢的,如果t_emp表中有1000条数据,那就会将子查询执行1000次

SELECT 
	e2.ename
FROM
	t_emp e1, t_emp e2
WHERE
	e1.ename = 'SCOTT' AND e2.ename != 'SCOTT' AND e1.deptno = e2.deptno;

其中:

SELECT 
	*
FROM
	t_emp e1, t_emp e2
WHERE
	e1.ename = 'SCOTT' AND e2.ename != 'SCOTT' 

这部分是找到SCOTT的所有同事,然后再找到相同部门的

image.png

总体思路应该是,求出平均底薪,然后把它当成一张表,和原来的员工表进行连接,然后再筛选

SELECT e.ename, e.deptno, e.sal
FROM t_emp e, (SELECT AVG(sal) avg FROM t_emp) t
WHERE e.sal > avg;

image.png

SELECT COUNT(*), MAX(e.sal), MIN(e.sal), AVG(e.sal), AVG(DATEDIFF(NOW(),e.hiredate)/365)
FROM t_emp e, t_dept d
WHERE d.dname = 'RESEARCH' AND e.deptno = d.deptno;

image.png

SELECT 
	job, 
	MAX(e.sal +IFNULL(e.comm, 0)), 
	MIN(e.sal +IFNULL(e.comm, 0)), 
	AVG(e.sal +IFNULL(e.comm, 0)), 
	MAX(s.grade), MIN(s.grade)
FROM t_emp e, t_salgrade s
WHERE (e.sal +IFNULL(e.comm, 0)) BETWEEN s.losal and s.hisal
GROUP BY job;

image.png

SELECT
	e.ename, e.deptno, e.sal, avg
FROM 
	t_emp e, (SELECT deptno, AVG(sal) avg FROM t_emp GROUP BY deptno) t
WHERE 
  e.deptno = t.deptno AND e.sal >= t.avg;

4.4.2 外连接

image.png

内连接做条件比较的时候,陈浩就不会出现在结果集中。内连接是只会出现满足连接条件的记录

image.png

  • 左连接:保留所有左表的信息去和右表进行连接
    • 右表满足条件直接连接
    • 右表不满足条件,用NULL跟坐标连接

image.png

image.png

40部门没有员工,不能使用内连接;要保留40部门,就要使用外连接

SELECT d.dname, COUNT(*)
FROM t_dept d LEFT JOIN t_emp e ON d.deptno = e.deptno
GROUP BY d.deptno; 

image.png

40部门没有人,为什么结果是1呢?COUNT统计的是有效记录条数,带NULL值的也算

SELECT d.dname, COUNT(e.deptno)
FROM t_dept d LEFT JOIN t_emp e ON d.deptno = e.deptno
GROUP BY d.deptno; 

image.png

不能简单的使用右外连接,要使用UNION

image.png

SELECT d.dname, COUNT(e.deptno)
    FROM t_dept d RIGHT JOIN t_emp e ON d.deptno = e.deptno
GROUP BY d.deptno; 

image.png

使用UNION合并左右连接的结果

(
SELECT d.dname, COUNT(e.deptno)
    FROM t_dept d LEFT JOIN t_emp e ON d.deptno = e.deptno
GROUP BY d.deptno; 
)
UNION
(
SELECT d.dname, COUNT(*)
    FROM t_dept d RIGHT JOIN t_emp e ON d.deptno = e.deptno
GROUP BY d.deptno; 
)

image.png

4.5 子查询

image.png

where子句中不推荐使用子查询,应该改为表连接的写法

image.png

4.5.1 按照子查询的位置划分

4.5.1.1 where子查询

image.png

4.5.1.2 from子查询

image.png

4.5.1.3 select子查询

image.png

4.5.2 按照结果集的数量划分

4.5.2.1 单行子查询和多行子查询

image.png

SELECT ename
FROM t_emp
WHERE
deptno IN
(SELECT deptno FROM t_emp WHERE ename IN ("FORD","MARTIN"))
AND ename NOT IN("FORD","MARTIN");

image.png

  • ALL:比所有
  • ANY:比任意一个

image.png

# 查询工资等级是3级或者4级的员工信息
SELECT empno, ename, sal
FROM t_emp
WHERE EXISTS (
    SELECT * FROM t_salgrade WHERE sal BETWEEN losal AND hisal AND grade IN(3,4)
);