《MySQL数据库》关联查询
一、关联查询
1、概念
在查询数据时,所需要的数据不只在一张表中,可能在两张或多张表中。这个时候,需要同时操作这些表来查询数据,即关联查询。
关联查询所涉及到的表与表之间都会存在有关联的字段,如员工表的部门编号和部门表的部门编号。
2、笛卡尔积
在做关联查询时,数据库会使用某一张表中的每一条记录都与另外一张表的所有记录进行组合。比如表A有x条记录,表B有y条记录,最终组合数为x*y,这个值就是笛卡尔积,通常没有意义。
3、等值连接
在做关联查询时,这些表中存在着有关联的两个字段。我们使用某一张表中的一条记录通过相关联的字段与另外一张表的记录进行匹配,组合成一条新的记录。使用"="连接关联字段
需求1:查询员工的姓名,职位及其所在部门的名称 、地址
4、内连接
内连接返回所有满足条件的记录,关键字join on。查询效果与等值连接一样。
用法:表A [inner] join 表B on 关联条件
5、外连接
在做关联查询时,我们所需要的数据,除了那些满足关联条件的数据外,还有不满足关联条件的数据。此时需要使用外连接。
会涉及到两个概念:
驱动表(主表):除了显示满足条件的数据,还需要显示不满足条件的数据的表
从表(副表):只显示满足关联条件的数据的表
mysql外连接只支持左外连接,右外连接,不支持全外连接
左外连接:
表A left [outer] join 表B on 关联条件。
表A是驱动表,表B是从表
右外连接
表A right [outer] join 表B on 关联条件
表B是驱动表,表A是从表
全外连接:
两张表的数据不管满不满足条件,都做显示。
表A full [outer] join 表B on 关联条件
PS:mysql 不支持全外连接
需求1:查询所有员工的姓名,职位,及其部门编号,部门名称----分析:员工表为驱动表,部门表为从表
select e.ename,e.job,e.deptno,d.dname from emp e left join dept d on e.deptno = d.deptno;
6、自连接
自连接是一种特殊的关联查询。数据的来源是同一个表,这样的表内的多个字段要存有关系。我们要使用表别名来虚拟出两个表。
需求1:查询员工姓名,职位及其上司姓名,职位。
mysql > select a.ename 员工姓名,
a.job 员工职位,
b.ename 上司姓名,
b.job 上司职位
from emp a join emp b on a.mgr=b.empno;
分析:可以看出 a的mgr与b的empno关联,所以,a是员工表,b是领导表
二、高级关联查询
有的时候,我们要查询的数据,一个简单的查询语句完成不了,并且我们使用的数据,表中不能直观体现出来。而是预先经过一次查询才会有所体现。那么先执行的查询,我们称之子查询。被子查询嵌入的查询语句称之为父查询或主查询。
主查询可以是select语句,也可以是DML语句或者是DDL语句。
根据子查询返回结果的不同,可以分为单行单列子查询、多行单列子查询、多行多列子查询。
子查询所在的位置,有可能出现在以下地方:
1)子查询可以在where子句中
2)子查询可以在from子句中
3)子查询可以在having子句中
4)子查询可以在select字句中,相当于外连接的另外一种写法。
1、在where子句中
需求1:查询和员工姓名scott同职位的员工信息。
select ename,job,hiredate,sal,deptno from emp where job=(select job from emp where ename='scott');
需求2:查询薪水比所有员工的平均薪水高的员工信息
mysql > select ename,job,hiredate,sal from emp where sal > (select avg(ifnull(sal,0)) from emp);
需求3:查询出部门中有salesman但是职位不是salesman的员工信息
select ename,job,hiredate,sal,deptno from emp where deptno in (select distinct deptno from emp where job='salesman') and job <> 'salesman';
exists 关键字
有时候,子查询需要引用主查询的字段数据,我们使用exists关键字。exists后面的子查询至少返回一条记录,则整个条件为true;
需求:查询有员工的部门信息
mysql > select deptno,dname,loc from dept d where exists (select * from emp e where d.deptno =e.deptno);
2、在from子句中
from子句用于指定表,如果想在一个子查询的结果里继续查询,则子查询需要写在from子句中,相当于一个表。
需求1:查询工资大于本部门平均工资的员工的信息。
mysql > select e.ename,e.sal,t.avg_sal,t.deptno from emp e join (select deptno,avg(ifnull(sal,0)) 'avg_sal' from emp group by deptno) t on e.deptno = t.deptno and e.sal>t.avg_sal order by t.deptno;
需求2:查询每个员工的工资,姓名和其部门的平均工资。
select e.ename, e.sal, t.avg_sal from emp e , (select deptno,avg(ifnull(sal,0)) 'avg_sal' from emp group by deptno) t where e.deptno = t.deptno order by t.deptno;
3、在having子句中
需求:查询平均工资大于30号部门平均工资的部门号、平均工资
mysql > select deptno,avg(ifnull(sal,0)) from emp group by deptno having avg(ifnull(sal,0))>(select avg(ifnull(sal,0)) from emp where deptno=30);
4、在select子句中
需求1:查询每个员工的姓名,工资,及其部门的平均工资,工资之和
select ename,sal,
(select avg(ifnull(sal,0)) from emp a where a.deptno=b.deptno) avg_sal ,
(select sum(sal) from emp c where c.deptno=b.deptno ) sum_sal
from emp b order by b.deptno;
上一篇: 数据库关联查询