3-1-3 MySQL基础-数据库的高级查询

测试表结构

 1 DROP TABLE IF EXISTS `t_emp`;
 2 CREATE TABLE `t_emp` (
 3   `empno` int(4) NOT NULL,
 4   `ename` varchar(20) DEFAULT NULL,
 5   `job` varchar(20) DEFAULT NULL,
 6   `mgr` int(4) DEFAULT NULL,
 7   `hiredate` date DEFAULT NULL,
 8   `sal` decimal(10,2) DEFAULT NULL,
 9   `comm` decimal(10,2) DEFAULT NULL,
10   `deptno` int(2) DEFAULT NULL,
11   PRIMARY KEY (`empno`)
12 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
13 
14 DROP TABLE IF EXISTS `t_dept`;
15 CREATE TABLE `t_dept` (
16   `deptno` int(2) NOT NULL,
17   `dname` varchar(20) DEFAULT NULL,
18   `loc` varchar(20) DEFAULT NULL,
19   PRIMARY KEY (`deptno`)
20 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

聚合函数

SUM函数

SUM函数用于求和,只能用于数字类型,字符类型的统计结果为0,日期类型统计结果是毫秒数相加

1 SELECT SUM(ename), SUM(sal) FROM t_emp;

 

 注意SUM函数求和会排除NULL值

MAX函数

MAX函数用于获取非空值的最大值

1 SELECT MAX(comm) FROM t_emp;

 

MIN函数

MIN函数用于获取非空值的最小值

1 SELECT MIN(comm) FROM t_emp;

 

 AVG函数

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

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

 

COUNT函数

COUNT(*)用于获得主键条数,COUNT(列名)用于获得包含非空值的记录数.

1 SELECT COUNT(*), COUNT(comm) FROM t_emp;

 

 分组查询

默认情况下聚合函数是对全表范围内的数据做统计

GROUP BY子句的作用是通过一定的规则蒋一个数据集划分成若干个小的区域,然后针对每个小区域分进行数据聚合处理

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

 

 对SELECT子句要求

查询语句中含有GROUP BY子句,那么SELECT子句中的内容就必须遵守规定:SELECT子句中可以包括聚合函数,或者GROUP BY子句的分组列,其余内容均不可以出现在SELECT子句中.

WITH ROLLUP

在group分组字段的基础上再进行统计数据

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

 

 GROUP_CONCAT函数

GROUP_CONCAT函数可以把分组查询中的某个字段拼成一个字符串

1 SELECT deptno, GROUP_CONCAT(ename),COUNT(*) 
2 FROM t_emp 
3 WHERE sal >=2000
4 GROUP BY deptno;

 

 GROUP BY语句在查询语句的执行顺序

FROM -> WHERE -> GROUP BY -> SELECT -> ORDER BY -> LIMIT

HAVING子句

因为WHERE子句先于GROUP BY,一旦WHERE中出现了聚合函数,数据库根本不知道按照什么范围计算聚合值,此时需要HAVING子句

1 SELECT deptno 
2 FROM t_emp
3 WHERE hiredate >= '1982-01-01'
4 GROUP BY deptno
5 HAVING COUNT(*) >=2
6 ORDER BY deptno;

 

HAVING子句的特殊用法

按照数字1分组,MySQL会根据SELECT子句中的列进行分组,HAVING子句也可以正常执行

1 SELECT deptno,COUNT(*) 
2 FROM t_emp
3 GROUP BY 1
4 HAVING deptno IN (10,20);

 表连接查询

表连接查询必须指定关联条件,否则会产生笛卡尔积

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

表连接的分类

表连接分为两种:内连接和外连接

内连接是结果集中只保留符合连接条件的记录

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

内连接

语法:

SELECT ...... FROM 表1

[INNER] JOIN 表2 ON 条件

[INNER] JOIN 表3 ON 条件

......;

内连接多种语法形式

1.SELECT ...... FROM 表1 JOIN 表2 ON 连接条件;

2.SELECT ...... FROM 表1 JOIN 表2 WHERE 连接条件;

3.SELECT ...... FROM 表1, 表2 WHERE 连接条件;

练习

查询与SCOTT相同部门的员工都有谁

1 SELECT  e1.ename
2 FROM t_emp e1
3 WHERE e1.deptno = (SELECT e2.deptno FROM t_emp e2 WHERE e2.ename = 'SCOTT')
4 AND e1.ename != 'SCOTT';

不建议使用子查询,因为遍历e1.deptno时每次都会运行一次子查询.效率低

建议改成表连接,如下

1 SELECT e2.ename
2 FROM t_emp e1 JOIN t_emp e2
3 ON e1.deptno = e2.deptno
4 WHERE e1.ename = 'SCOTT' AND e2.ename != 'SCOTT';

查询月薪超过公司平均月薪的员工信息

1 SELECT e1.empno,e1.ename,e1.sal
2 FROM t_emp e1
3 JOIN (
4       SELECT AVG(e2.sal) avg_sal
5       FROM t_emp e2) t ON e1.sal > t.avg_sal;

外连接

左连接和右连接

左外连接就是保留左表所有的记录,与右表做连接.如果游标有符合条件的记录就与左表连接.如果右表没有符合条件的记录,就用NULL与左表连接.右外连接也是如此.

子查询

子查询可以写在三个地方:WHERE子句,FROM子句,SELECT子句,但是只有FROM子句才是最可取的

WHERE子查询

这种子查询最简单,最容易理解,但是效率很低,比较每条记录时都要重新执行子查询,请用表连接替代WHERE子查询.

FROM子查询

FROM子查询只会执行一次,所以查询效率很高

SELECT子查询

SELECT子查询每输出一条记录都要执行一次,查询效率很低

相关子查询

查询执行的时候要多次依赖子查询的结果,这种查询被称为相关子查询

WHERE子查询和SELECT子查询都属于相关子查询

因为相关子查询要反复多次执行,所以应该避免使用

 多行子查询

WHERE子句中可以使用IN,ALL,ANY,EXISTS关键字处理多行表达式结果集的条件判断

1 SELECT ename
2 FROM t_emp
3 WHERE sal >= ALL
4 (SELECT sal FROM t_emp WHERE ename IN ("FORD", "MARTIN"))
5 AND ename NOT IN ("FORD","MARTIN");

EXISTS关键字是把原来在子查询之外的条件判断,写到子查询里面

SELECT ...... FROM 表名 WHERE [NOT] EXISTS (子查询);

posted @ 2020-09-18 07:34  mingmingn  阅读(164)  评论(0)    收藏  举报