MySQL基础02 - 内连接、外连接、三张表连接、子查询、union、limit

查询结果集的去重

/*

mysql> select distinct job from emp;// distinct关键字去重重复记录。
+-----------+
| job       |
+-----------+
| CLERK     |
| SALESMAN  |
| MANAGER   |
| ANALYST   |
| PRESIDENT |
+-----------+
		
mysql> select ename, distinct job from emp;
以上的sql语句是错误的。
记住:distinct只能出现在所有字段的最前面。

mysql> select distinct deptno,job from emp;
deptno和job联合去重
+--------+-----------+
| deptno | job       |
+--------+-----------+
|     20 | CLERK     |
|     30 | SALESMAN  |
|     20 | MANAGER   |
|     30 | MANAGER   |
|     10 | MANAGER   |
|     20 | ANALYST   |
|     10 | PRESIDENT |
|     30 | CLERK     |
|     10 | CLERK     |
+--------+-----------+

案例:统计岗位的数量?
select count(distinct job) from emp;
+---------------------+
| count(distinct job) |
+---------------------+
|                   5 |
+---------------------+

*/

连接查询

/*
2.1、什么是连接查询?
	在实际开发中,大部分的情况下都不是从单表中查询数据,一般都是多张表联合查询取出最终的结果。
	在实际开发中,一般一个业务都会对应多张表,比如:学生和班级,起码两张表。
	stuno    stuname    classno    classname
	----------------------------------------
	1        zs          1         高三1班
	2        ls          1         高三2班
	学生和班级信息存储到一张表中,结果就像上面一样,数据会存在大量的重复,导致数据的冗余。
2.2、连接查询的分类?

	根据语法出现的年代来划分的话,包括:
	SQL92(一些老的DBA可能还在使用这种语法。DBA:DataBase Administrator,数据库管理员)
	SQL99(比较新的语法)

	根据表的连接方式来划分,包括:
		内连接:
			等值连接
			非等值连接
			自连接
		外连接:
			左外连接(左连接)
			右外连接(右连接)
		全连接(这个不讲,很少用!)
	
2.3、在表的连接查询方面有一种现象称为:笛卡尔积现象。(笛卡尔乘积现象)

案例:找出每一个员工的部门名称,要求显示员工名和部门名。
EMP表
+--------+--------+
| ename  | deptno |
+--------+--------+
| SMITH  |     20 |
| ALLEN  |     30 |
| WARD   |     30 |
| JONES  |     20 |
| MARTIN |     30 |
| BLAKE  |     30 |
| CLARK  |     10 |
| SCOTT  |     20 |
| KING   |     10 |
| TURNER |     30 |
| ADAMS  |     20 |
| JAMES  |     30 |
| FORD   |     20 |
| MILLER |     10 |
+--------+--------+
DEPT表
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+

select ename,dname from emp, dept;
+--------+------------+
| ename  | dname      |
+--------+------------+
| SMITH  | ACCOUNTING |
| SMITH  | RESEARCH   |
| SMITH  | SALES      |
| SMITH  | OPERATIONS |
| ALLEN  | ACCOUNTING |
| ALLEN  | RESEARCH   |
| ALLEN  | SALES      |
| ALLEN  | OPERATIONS |
...
56 rows in set (0.00 sec)

笛卡尔积现象:当两张表进行连接查询的时候,没有任何条件进行限制,最终的查询结果条数是两张表记录条数的乘积。

关于表的别名:
	select e.ename,d.dname from emp e, dept d;
	表的别名有什么好处?
		第一:执行效率高。
		第二:可读性好。

2.4、怎么避免笛卡尔积现象?当然是加条件进行过滤。
思考:避免了笛卡尔积现象,会减少记录的匹配次数吗?
	不会,次数还是56次,只不过显示的是有效记录。(*****)

案例:找出每一个员工的部门名称,要求显示员工名和部门名。
	select 
		e.ename, d.dname 
	from 
		emp e, dept d 
	where 
		e.deptno = d.deptno; //SQL92,以后不用
	+--------+------------+
	| ename  | dname      |
	+--------+------------+
	| CLARK  | ACCOUNTING |
	| KING   | ACCOUNTING |
	| MILLER | ACCOUNTING |
	| SMITH  | RESEARCH   |
	| JONES  | RESEARCH   |
	| SCOTT  | RESEARCH   |
	| ADAMS  | RESEARCH   |
	| FORD   | RESEARCH   |
	| ALLEN  | SALES      |
	| WARD   | SALES      |
	| MARTIN | SALES      |
	| BLAKE  | SALES      |
	| TURNER | SALES      |
	| JAMES  | SALES      |
	+--------+------------+

2.5、内连接之等值连接:最大特点是:条件是等量关系。

案例:查询每个员工的部门名称,要求显示员工名和部门名。
SQL92:(太老,不用了)
	select 
		e.ename, d.dname 
	from 
		emp e, dept d 
	where 
		e.deptno = d.deptno;

SQL99:(常用的)
	select 
		e.ename, d.dname 
	from 
		emp e 
	join 
		dept d 
	on 
		e.deptno = d.deptno;
	
	// inner可以省略,带着inner的目的是可读性更强一些。
	select 
		e.ename, d.dname 
	from 
		emp e 
	inner join 
		dept d 
	on 
		e.deptno = d.deptno;
	
	语法:
		...
			A
		join
			B
		on
			连接条件
		where
			...

	SQL99语法结构更清晰一些: 表的连接条件和后来的where条件分离了。
	+--------+------------+
	| ename  | dname      |
	+--------+------------+
	| CLARK  | ACCOUNTING |
	| KING   | ACCOUNTING |
	| MILLER | ACCOUNTING |
	| SMITH  | RESEARCH   |
	| JONES  | RESEARCH   |
	| SCOTT  | RESEARCH   |
	| ADAMS  | RESEARCH   |
	| FORD   | RESEARCH   |
	| ALLEN  | SALES      |
	| WARD   | SALES      |
	| MARTIN | SALES      |
	| BLAKE  | SALES      |
	| TURNER | SALES      |
	| JAMES  | SALES      |
	+--------+------------+

2.6、内连接之非等值连接:最大的特点是:连接条件中的关系是非等量关系。

案例:找出每个员工的工资等级,要求显示员工名、工资、工资等级。
// 员工表
mysql> select ename,sal from emp;
+--------+---------+
| ename  | sal     |
+--------+---------+
| SMITH  |  800.00 |
| ALLEN  | 1600.00 |
| WARD   | 1250.00 |
| JONES  | 2975.00 |
| MARTIN | 1250.00 |
| BLAKE  | 2850.00 |
| CLARK  | 2450.00 |
| SCOTT  | 3000.00 |
| KING   | 5000.00 |
| TURNER | 1500.00 |
| ADAMS  | 1100.00 |
| JAMES  |  950.00 |
| FORD   | 3000.00 |
| MILLER | 1300.00 |
+--------+---------+
// 工资等级表
mysql> select * from salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |
+-------+-------+-------+

select 
	e.ename,e.sal,s.grade 
from 
	emp e 
join 
	salgrade s 
on 
	e.sal between s.losal and s.hisal;
	
// inner可以省略
select 
	e.ename,e.sal,s.grade 
from 
	emp e 
inner join 
	salgrade s 
on 
	e.sal between s.losal and s.hisal;
+--------+---------+-------+
| ename  | sal     | grade |
+--------+---------+-------+
| SMITH  |  800.00 |     1 |
| ALLEN  | 1600.00 |     3 |
| WARD   | 1250.00 |     2 |
| JONES  | 2975.00 |     4 |
| MARTIN | 1250.00 |     2 |
| BLAKE  | 2850.00 |     4 |
| CLARK  | 2450.00 |     4 |
| SCOTT  | 3000.00 |     4 |
| KING   | 5000.00 |     5 |
| TURNER | 1500.00 |     3 |
| ADAMS  | 1100.00 |     1 |
| JAMES  |  950.00 |     1 |
| FORD   | 3000.00 |     4 |
| MILLER | 1300.00 |     2 |
+--------+---------+-------+

2.7、内连接之自连接:最大的特点是:一张表看做两张表,自己连接自己。

案例:找出每个员工的上级领导,要求显示员工名和对应的领导名。
mysql> select empno,ename,mgr from emp;
emp a 员工表
+-------+--------+------+
| empno | ename  | mgr  |
+-------+--------+------+
|  7369 | SMITH  | 7902 |  // mar --> FORD
|  7499 | ALLEN  | 7698 |
|  7521 | WARD   | 7698 |
|  7566 | JONES  | 7839 |
|  7654 | MARTIN | 7698 |
|  7698 | BLAKE  | 7839 |
|  7782 | CLARK  | 7839 |
|  7788 | SCOTT  | 7566 |
|  7839 | KING   | NULL |
|  7844 | TURNER | 7698 |
|  7876 | ADAMS  | 7788 |
|  7900 | JAMES  | 7698 |
|  7902 | FORD   | 7566 |
|  7934 | MILLER | 7782 |
+-------+--------+------+

emp b 领导表
+-------+--------+
| empno | ename  |
+-------+--------+
|  7566 | JONES  |
|  7698 | BLAKE  |
|  7782 | CLARK  |
|  7788 | SCOTT  |
|  7839 | KING   |
|  7902 | FORD   |
+-------+--------+

员工的领导编号 = 领导的员工编号

select 
	a.ename as '员工名',b.ename as '领导名'  
from  
	emp a 
inner join 
	emp b 
on  
	a.mgr = b.empno; 

+--------+--------+
| 员工名 | 领导名  |
+--------+--------+
| SMITH  | FORD   |
| ALLEN  | BLAKE  |
| WARD   | BLAKE  |
| JONES  | KING   |
| MARTIN | BLAKE  |
| BLAKE  | KING   |
| CLARK  | KING   |
| SCOTT  | JONES  |
| TURNER | BLAKE  |
| ADAMS  | SCOTT  |
| JAMES  | BLAKE  |
| FORD   | JONES  |
| MILLER | CLARK  |
+--------+--------+
// 13条记录,KING没有上级领导就没显示

2.8、外连接
什么是外连接,和内连接有什么区别?
	内连接:
		假设A和B表进行内连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是内连接。
		AB两张表没有主副之分,两张表是平等的。
	外连接:
		假设A和B表进行连接,使用外连接的话,AB两张表中有一张表是主表,一张表是副表,主要查询主表中
		的数据。捎带着查询副表,当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配。
	
	外连接的分类?
		左外连接(左连接):表示左边的这张表是主表。
		右外连接(右连接):表示右边的这张表是主表。
		
		左连接有右连接的写法,右连接也会有对应的左连接的写法。
		
案例:找出每个员工的上级领导?(所有员工必须全部查询出来)
emp a 员工表
+-------+--------+------+
| empno | ename  | mgr  |
+-------+--------+------+
|  7369 | SMITH  | 7902 |  
|  7499 | ALLEN  | 7698 |
|  7521 | WARD   | 7698 |
|  7566 | JONES  | 7839 |
|  7654 | MARTIN | 7698 |
|  7698 | BLAKE  | 7839 |
|  7782 | CLARK  | 7839 |
|  7788 | SCOTT  | 7566 |
|  7839 | KING   | NULL |
|  7844 | TURNER | 7698 |
|  7876 | ADAMS  | 7788 |
|  7900 | JAMES  | 7698 |
|  7902 | FORD   | 7566 |
|  7934 | MILLER | 7782 |
+-------+--------+------+

emp b 领导表
+-------+--------+
| empno | ename  |
+-------+--------+
|  7566 | JONES  |
|  7698 | BLAKE  |
|  7782 | CLARK  |
|  7788 | SCOTT  |
|  7839 | KING   |
|  7902 | FORD   |
+-------+--------+

内连接:
select  
	a.ename '员工', b.ename '领导'  
from 
	emp a 
inner join 
	emp b 
on 
	a.mgr = b.empno; 

外连接:(左外连接/左连接)
select  
	a.ename '员工', b.ename '领导'  
from 
	emp a 
left join 
	emp b 
on 
	a.mgr = b.empno; 

// outer可以省略
select  
	a.ename '员工', b.ename '领导'  
from 
	emp a 
left outer join 
	emp b 
on 
	a.mgr = b.empno; 
	
外连接:(右外连接/右连接)
select  
	a.ename '员工', b.ename '领导'  
from 
	emp b 
right join 
	emp a  
on 
	a.mgr = b.empno; 
+--------+-------+
| 员工    | 领导  |
+--------+-------+
| SMITH  | FORD  |
| ALLEN  | BLAKE |
| WARD   | BLAKE |
| JONES  | KING  |
| MARTIN | BLAKE |
| BLAKE  | KING  |
| CLARK  | KING  |
| SCOTT  | JONES |
| KING   | NULL  |
| TURNER | BLAKE |
| ADAMS  | SCOTT |
| JAMES  | BLAKE |
| FORD   | JONES |
| MILLER | CLARK |
+--------+-------+
// 14条记录,KING仍然显示出来,副表为NULL

外连接最重要的特点是:主表的数据无条件的全部查询出来。

案例:找出哪个部门没有员工?
mysql> select * from emp;
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
|  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
14 rows in set (0.00 sec)

mysql> select * from dept;
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+

select 
	e.*, d.*
from 
	emp e 
right join 
	dept d 
on 
	e.deptno = d.deptno; 
+-------+--------+-----------+------+------------+---------+---------+--------+--------+------------+----------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO | DEPTNO | DNAME      | LOC      |
+-------+--------+-----------+------+------------+---------+---------+--------+--------+------------+----------+
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |     10 | ACCOUNTING | NEW YORK |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |     10 | ACCOUNTING | NEW YORK |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |     10 | ACCOUNTING | NEW YORK |
|  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |     20 | RESEARCH   | DALLAS   |
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |     30 | SALES      | CHICAGO  |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |     30 | SALES      | CHICAGO  |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |     30 | SALES      | CHICAGO  |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |     30 | SALES      | CHICAGO  |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |     30 | SALES      | CHICAGO  |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |     30 | SALES      | CHICAGO  |
|  NULL | NULL   | NULL      | NULL | NULL       |    NULL |    NULL |   NULL |     40 | OPERATIONS | BOSTON   |
+-------+--------+-----------+------+------------+---------+---------+--------+--------+------------+----------+

继续加where查询条件:
select 
	e.*, d.*
from 
	emp e 
right join 
	dept d 
on 
	e.deptno = d.deptno 
where 
	e.empno is null; 
+-------+-------+------+------+----------+------+------+--------+--------+------------+--------+
| EMPNO | ENAME | JOB  | MGR  | HIREDATE | SAL  | COMM | DEPTNO | DEPTNO | DNAME      | LOC    |
+-------+-------+------+------+----------+------+------+--------+--------+------------+--------+
|  NULL | NULL  | NULL | NULL | NULL     | NULL | NULL |   NULL |     40 | OPERATIONS | BOSTON |
+-------+-------+------+------+----------+------+------+--------+--------+------------+--------+

题意:保留d.*即可。
select 
	d.*
from 
	emp e 
right join 
	dept d 
on 
	e.deptno = d.deptno 
where 
	e.empno is null; 
+--------+------------+--------+
| DEPTNO | DNAME      | LOC    |
+--------+------------+--------+
|     40 | OPERATIONS | BOSTON |
+--------+------------+--------+

2.9、三张表怎么连接查询?

案例:找出每一个员工的部门名称以及工资等级。
mysql> select empno,ename,deptno,sal from emp;
EMP e
+-------+--------+--------+---------+
| empno | ename  | deptno | sal     |
+-------+--------+--------+---------+
|  7369 | SMITH  |     20 |  800.00 |
|  7499 | ALLEN  |     30 | 1600.00 |
|  7521 | WARD   |     30 | 1250.00 |
|  7566 | JONES  |     20 | 2975.00 |
|  7654 | MARTIN |     30 | 1250.00 |
|  7698 | BLAKE  |     30 | 2850.00 |
|  7782 | CLARK  |     10 | 2450.00 |
|  7788 | SCOTT  |     20 | 3000.00 |
|  7839 | KING   |     10 | 5000.00 |
|  7844 | TURNER |     30 | 1500.00 |
|  7876 | ADAMS  |     20 | 1100.00 |
|  7900 | JAMES  |     30 |  950.00 |
|  7902 | FORD   |     20 | 3000.00 |
|  7934 | MILLER |     10 | 1300.00 |
+-------+--------+--------+---------+

mysql> select * from dept;
DEPT d
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+

mysql> select * from salgrade;
SALGRADE s
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |
+-------+-------+-------+

注意,解释一下:
	...
		A
	join
		B
	join
		C
	on
	...
	表示:A表和B表先进行表连接,连接之后A表继续和C表进行连接。
	
	select 
		e.ename, d.dname, s.grade 
	from 
		emp e 
	join 
		dept d 
	on 
		e.deptno = d.deptno 
	join 
		salgrade s 
	on 
		e.sal between s.losal and s.hisal; 
	+--------+------------+-------+
	| ename  | dname      | grade |
	+--------+------------+-------+
	| SMITH  | RESEARCH   |     1 |
	| ALLEN  | SALES      |     3 |
	| WARD   | SALES      |     2 |
	| JONES  | RESEARCH   |     4 |
	| MARTIN | SALES      |     2 |
	| BLAKE  | SALES      |     4 |
	| CLARK  | ACCOUNTING |     4 |
	| SCOTT  | RESEARCH   |     4 |
	| KING   | ACCOUNTING |     5 |
	| TURNER | SALES      |     3 |
	| ADAMS  | RESEARCH   |     1 |
	| JAMES  | SALES      |     1 |
	| FORD   | RESEARCH   |     4 |
	| MILLER | ACCOUNTING |     2 |
	+--------+------------+-------+

	案例:找出每一个员工的部门名称、工资等级以及上级领导。
	select 
		e.ename '员工', d.dname '部门名称', s.grade '工资等级', e1.ename '领导' 
	from 
		emp e 
	join 
		dept d 
	on 
		e.deptno = d.deptno 
	join 
		salgrade s 
	on 
		e.sal between s.losal and s.hisal 
	left join 
		emp e1 
	on 
		e.mgr = e1.empno; 
+--------+------------+----------+-------+
| 员工   | 部门名称    | 工资等级  | 领导   |
+--------+------------+----------+-------+
| SMITH  | RESEARCH   |        1 | FORD  |
| ALLEN  | SALES      |        3 | BLAKE |
| WARD   | SALES      |        2 | BLAKE |
| JONES  | RESEARCH   |        4 | KING  |
| MARTIN | SALES      |        2 | BLAKE |
| BLAKE  | SALES      |        4 | KING  |
| CLARK  | ACCOUNTING |        4 | KING  |
| SCOTT  | RESEARCH   |        4 | JONES |
| KING   | ACCOUNTING |        5 | NULL  |
| TURNER | SALES      |        3 | BLAKE |
| ADAMS  | RESEARCH   |        1 | SCOTT |
| JAMES  | SALES      |        1 | BLAKE |
| FORD   | RESEARCH   |        4 | JONES |
| MILLER | ACCOUNTING |        2 | CLARK |
+--------+------------+----------+-------+

3、子查询

3.1、什么是子查询?子查询都可以出现在哪里?
	select语句当中嵌套select语句,被嵌套的select语句是子查询。
	子查询可以出现在哪里?
		select
			..(select)
		from
			..(select)
		where
			..(select)
			
3.2、where字句中使用了子查询

案例:找出高于平均薪资的员工信息。
select * from emp sal > avg(sal);// 错误的写法,where后面不能直接使用分组函数。
select * from emp where sal > (select avg(sal) from emp);

3.3、from后面嵌套子查询

案例:找出每个部门平均薪水的薪资等级。
第一步:找出每个部门平均薪水(按照部门编号分组,求sal的平均值)
select deptno,avg(sal) as avgsal from emp group by deptno;
+--------+-------------+
| deptno | avgsal      |
+--------+-------------+
|     10 | 2916.666667 |
|     20 | 2175.000000 |
|     30 | 1566.666667 |
+--------+-------------+
第二步:将以上的查询结果当做临时表t,让t表和salgrade s表连接。条件是:t.avgsal between s.losal and s.hisal。
select 
	t.*, s.grade 
from 
	(select deptno,avg(sal) as avgsal from emp group by deptno) t 
join 
	salgrade s 
on  
	t.avgsal between s.losal and s.hisal; 
+--------+-------------+-------+
| deptno | avgsal      | grade |
+--------+-------------+-------+
|     30 | 1566.666667 |     3 |
|     10 | 2916.666667 |     4 |
|     20 | 2175.000000 |     4 |
+--------+-------------+-------+

案例:找出每个部门平均的薪水等级。
第一步:找出每个员工的薪水等级。
mysql> 
	select 
		e.ename,e.sal,e.deptno,s.grade 
	from 
		emp e 
	join 
		salgrade s
	on 
		e.sal between s.losal and s.hisal;
+--------+---------+--------+-------+
| ename  | sal     | deptno | grade |
+--------+---------+--------+-------+
| SMITH  |  800.00 |     20 |     1 |
| ALLEN  | 1600.00 |     30 |     3 |
| WARD   | 1250.00 |     30 |     2 |
| JONES  | 2975.00 |     20 |     4 |
| MARTIN | 1250.00 |     30 |     2 |
| BLAKE  | 2850.00 |     30 |     4 |
| CLARK  | 2450.00 |     10 |     4 |
| SCOTT  | 3000.00 |     20 |     4 |
| KING   | 5000.00 |     10 |     5 |
| TURNER | 1500.00 |     30 |     3 |
| ADAMS  | 1100.00 |     20 |     1 |
| JAMES  |  950.00 |     30 |     1 |
| FORD   | 3000.00 |     20 |     4 |
| MILLER | 1300.00 |     10 |     2 |
+--------+---------+--------+-------+
第二步:基于以上结果,继续按照deptno分组,求grade平均值。
	select 
		e.deptno,avg(s.grade) 
	from 
		emp e 
	join 
		salgrade s 
	on 
		e.sal between s.losal and s.hisal 
	group by 
		e.deptno;
	+--------+--------------+
	| deptno | avg(s.grade) |
	+--------+--------------+
	|     10 |       3.6667 |
	|     20 |       2.8000 |
	|     30 |       2.5000 |
	+--------+--------------+

3.4、在select后面嵌套子查询。
实例:找出每个员工所在的部门名称,要求显示员工名和部门名。
不用连接表的方式,使用嵌套查询方式。
select 
	e.ename, e.deptno, (select d.dname from dept d where e.deptno = d.deptno) as dname 
from 
		emp e;
+--------+--------+------------+
| ename  | deptno | dname      |
+--------+--------+------------+
| SMITH  |     20 | RESEARCH   |
| ALLEN  |     30 | SALES      |
| WARD   |     30 | SALES      |
| JONES  |     20 | RESEARCH   |
| MARTIN |     30 | SALES      |
| BLAKE  |     30 | SALES      |
| CLARK  |     10 | ACCOUNTING |
| SCOTT  |     20 | RESEARCH   |
| KING   |     10 | ACCOUNTING |
| TURNER |     30 | SALES      |
| ADAMS  |     20 | RESEARCH   |
| JAMES  |     30 | SALES      |
| FORD   |     20 | RESEARCH   |
| MILLER |     10 | ACCOUNTING |
+--------+--------+------------+

4、union(可以将查询结果相加)
案例:找出工作岗位是SALESMAN和MANAGER的员工?
第一种:select ename,job from emp where job = "salesman" or job = "manager";
第二种:select ename,job from emp where job in ("salesman", "manager");
+--------+----------+
| ename  | job      |
+--------+----------+
| ALLEN  | SALESMAN |
| WARD   | SALESMAN |
| JONES  | MANAGER  |
| MARTIN | SALESMAN |
| BLAKE  | MANAGER  |
| CLARK  | MANAGER  |
| TURNER | SALESMAN |
+--------+----------+
第三种:union
select ename,job from emp where job = "salesman" 
union 
select ename,job from emp where job = "manager";

两张不相干的表中的数据拼接在一起显示?
select ename from emp 
union 
select dname from dept;
+------------+
| ename      |
+------------+
| SMITH      |
| ALLEN      |
| WARD       |
| JONES      |
| MARTIN     |
| BLAKE      |
| CLARK      |
| SCOTT      |
| KING       |
| TURNER     |
| ADAMS      |
| JAMES      |
| FORD       |
| MILLER     |
| ACCOUNTING |
| RESEARCH   |
| SALES      |
| OPERATIONS |
+------------+

注意:union相加时,两方列数相同
mysql> select ename,sal from emp
    -> union
    -> select dname from dept;
ERROR 1222 (21000): The used SELECT statements have a different number of columns

5、limit(重点中的重点:以后分页查询全靠它了)

5.1、limit是mysql特有的,其他数据库中没有,不通用。

5.2、limit取结果集中的部分数据,这是它的作用。

5.3、语法机制:
	limit startIndex, length
		startIndex表示起始位置:从0开始,0表示第一条数据。
		length表示取几个
	
	案例:取出工资前5名的员工(思路:降序取前5个)
		select ename,sal from emp order by sal desc;
		取前5个:
		select ename,sal from emp order by sal desc limit 0, 5;
		select ename,sal from emp order by sal desc limit 5;
		+-------+---------+
		| ename | sal     |
		+-------+---------+
		| KING  | 5000.00 |
		| SCOTT | 3000.00 |
		| FORD  | 3000.00 |
		| JONES | 2975.00 |
		| BLAKE | 2850.00 |
		+-------+---------+
		
5.4、limit是sql语句最后执行的一个环节:
	select        5
		...
	from          1
		...
	where         2
		...
	group by      3
		...
	having        4
		...
	order by      6 
		...
	limit         7
		...;

5.5、案例:找到工资排名在第4到第9名的员工?
	select ename,sal from emp order by sal desc limit 3, 6;
	+--------+---------+
	| ename  | sal     |
	+--------+---------+
	| JONES  | 2975.00 |
	| BLAKE  | 2850.00 |
	| CLARK  | 2450.00 |
	| ALLEN  | 1600.00 |
	| TURNER | 1500.00 |
	| MILLER | 1300.00 |
	+--------+---------+

5.6、通用的标准分页sql?
每页显示3条记录:
第1页:0, 3
第2页:3, 3
第3页:6, 3
第4页:9, 3
第5页:12, 3
...

每页显示pageSize条记录:
第pageNo页:(pageNo-1) * pageSize, pageSize

pageSize是什么:每页显示多少条记录
pageNo是什么;显示第几页

java代码{
	int pageNo = 2; // 页码是2
	int pageSize = 10; // 每页显示10条
	
	limit (pageNo - 1) * pageSize, pageSize;
}
*/		

		

猜你喜欢

转载自blog.csdn.net/weixin_43636084/article/details/128198120