文章目录
- 一、基本查询回顾
- 二、多表查询
- (一)笛卡尔积的初步过滤
- (二)例子
- 1.显示部门号为10的部门名,员工名和工资
- 2.显示各个员工的姓名,工资,及工资级别
- 三、自连接
- (一)定义
- (二)显示员工FORD的上级领导的编号和姓名
- 四、子查询
- (一)单行子查询
- 1.显示SMITH同一部门的员工
- (二)多行子查询
- 1.in关键字
- 2.all关键字
- 五、合并查询
一、基本查询回顾
二、多表查询
- 实际开发中往往需要将多张表关联起来进行查询,即多表查询。
- 在进行多表查询时,只需将多张表的表名依次放到from子句后,用逗号隔开即可。
- MySQL将会对给定的这多张表取笛卡尔积,作为多表查询的初始数据源。
多表查询的本质,就是对给定的多张表取笛卡尔积,然后在笛卡尔积中进行查询。
对多张表取笛卡尔积,即得到这多张表的记录的所有可能有序对组成的集合,如下面对员工表和部门表进行多表查询,由于查询语句中没有指明筛选条件,因此最终得到的结果便是员工表和部门表的笛卡尔积!
(一)笛卡尔积的初步过滤
由于以上要查询的数据分别来自于emp表和dept表,因此要联合这两张表进行查询:
- 员工表和部门表的笛卡尔积由两部分组成,前半部分是员工表的列信息,后半部分是部门表的列信息。
- 对员工表和部门表取笛卡尔积时,会先从员工表中选出一条记录与部门表中的所有记录进行组合,然后再从员工表中选出一条记录与部门表中的所有记录进行组合,以此类推,最终得到的就是这两张表的笛卡尔积。
mysql> select *from DEPT,EMP ;
对多张表取笛卡尔积后得到的数据并不都是有意义的,如对员工表和部门表取笛卡尔积时,员工表中的每一个员工信息都会和部门表中的每一个部门信息进行组合,而实际一个员工只有和自己所在的部门信息进行组合才是有意义的,因此需要从笛卡尔积中筛选出员工的部门号和部门的编号相等记录!
注意:进行笛卡尔积的多张表中可能会存在相同的列名,在选中列名时需通过 表名.列名 的方式指明!
mysql> select *from DEPT,EMP where EMP.deptno = DEPT.deptno;
(二)例子
1.显示部门号为10的部门名,员工名和工资
由于部门名仅在部门表中,而员工名和员工工资仅在员工表中,因此需同时使用员工表和部门表进行多表查询,在where子句中指明筛选条件为员工的部门号等于部门编号,并且部门号为10的记录。
mysql> select ENAME,SAL,DNAME from EMP,DEPT where EMP.deptno = DEPT.deptno and DEPT.deptno=10;
2.显示各个员工的姓名,工资,及工资级别
员工名和工资仅在员工表中,工资级别仅在工资等级表中,因此需同时使用员工表和工资等级表进行多表查询,在where子句中指明筛选条件为员工的工资在losal和hisal之间的记录!
select ENAME,SAL,GRADE from EMP,salgrade where EMP.SAL between losal and hisal;
- 员工表和工资等级表的笛卡尔积中,将每一个员工的信息和每一个工资等级的信息都进行了组合,而实际一个员工只有和自己的工资对应的工资等级信息组合才有意义
- 因此需要根据各个工资等级的最低工资和最高工资判断一个员工是否属于该工资等级,进而筛选出有意义的记录
三、自连接
(一)定义
- 自连接是指在同一张表进行连接查询,即不仅可以取不同表的笛卡尔积,也可以对同一张表取笛卡尔积。
- 若一张表中的某个字段能够将表中的多条记录关联起来,那么就可以通过自连接将表中通过该字段关联的记录组合起来。
(二)显示员工FORD的上级领导的编号和姓名
- 解决该问题可使用子查询,先对员工表查询得到FORD的领导的编号,然后再根据领导的编号对员工表进行查询得到FORD领导的姓名。
select empno,ename from EMP where empno = (select empno from EMP where ename = 'FORD');
- 也可使用自连接解决该问题,因为员工表中的mgr字段能够将表中员工的信息和员工领导的信息关联起来
select leader.empno,leader.ename from EMP leader,EMP worker where leader.empno = worker.mgr and worker.ename='FORD';
注意: 自连接是对同一张表取笛卡尔积,因此在自连接时至少需给一张表取别名,否则无法区分这两张表中的列。
四、子查询
(一)单行子查询
单行子查询,即返回单行单列数据(唯一数据)的子查询!
1.显示SMITH同一部门的员工
在子查询中查询SMITH所在的部门号,在where子句中指明筛选条件为员工部门号等于子查询返回的部门号,并且员工的姓名不为SMITH。
mysql> select deptno from EMP where ename = 'SMITH';mysql> select *from EMP where deptno = (select deptno from EMP where ename = 'SMITH') and ename <> 'SMITH';
也可以使用自连接解决该问题,因为和SMITH同一部门的员工的信息也在员工表中,因此对员工表进行自连接后,在where子句中指明表1的员工姓名为SMITH,并且表1和表2的部门号必须相等,并且表2的员工姓名不为SMITH,这样也能筛选出和SMITH同一部门的员工信息!
(二)多行子查询
多行子查询,即返回多行数据(集合)的子查询!
1.in关键字
显示和10号部门的工作岗位相同的员工的名字、岗位、工资和部门号,但是不包含10号部门的员工。
select distinct job from EMP where deptno = 10;
mysql> select ename,job,sal,deptno from EMP where job in(select distinct job from EMP where deptno = 10) and deptno<>10;
2.all关键字
显示工资比30号部门的所有员工的工资高的员工的姓名、工资和部门号。
五、合并查询
合并查询,是指将多个查询结果进行合并,可使用的操作符有union和union all。
- union用于取得两个查询结果的并集,union会自动去掉结果集中的重复行。
- union all也用于取得两个查询结果的并集,但union all不会去掉结果集中的重复行。
显示工资大于2500或职位是MANAGER的员工