1 为什么会使用子查询
虽然可以通过连接查询来实现多表查询数据记录,但不建议使用,因为连接查询的性能很差。例如,我们要查询部门表dept和雇员表employee中的数据记录,一般可能会写成:
SELECT
*
FROM
dept t1,
employee t2
WHERE
t1.deptno = t2.deptno;
对于这条SQL语句,在数据库执行的时候,会先对两个表进行笛卡尔积操作,然后再选取符合条件 t1.deptno=t2.deptno 的数据记录。
由于笛卡尔积时是将两个表中的记录数做乘积生成新的记录,如果当两个表中的数据记录都比较多时,进行乘积操作时性能将会很差,甚至造成死机。为了解决该问题,我们可以使用子查询来实现多表查询。
2 什么是子查询
子查询:在一个查询中嵌套了其他若干查询,即在一个SELECT查询语句的FROM或WHERE字句中包含另一个SELECT查询语句。
在这种嵌套的查询语句中,外层的SELECT查询语句称为主查询,WHERE或FROM中的查询语句称为子查询,也叫嵌套查询。
通过子查询可以实现多表查询,子查询经常出现在WHERE或FROM字句中。 1、WHERE子句中的子查询:该位置处的子查询一般返回单行单列,多行单列,单行多列数据。就是返回能够作为WHERE子句查询条件的值。(子查询返回的值作为主查询的查询条件) 2、FROM子句中的子查询:该位置处的子查询一般返回多行多列数据,相当于是返回一张临时表,符合FROM子句后面是表的规则,主查询再从这个临时表中查询满足条件的数据。
3 子查询的具体使用
emp表如下: dept表如下:
3.1 WHERE子句后使用子查询
1、返回结果为单行单列的子查询(就是有一个查询字段一个取值的情况) 示例:查询部门编号小于“SALES”的部门编号的员工记录
SELECT
*
FROM
emp
WHERE
deptno < ( SELECT deptno FROM dept WHERE dname = "SALES" );
2、返回结果为单行多列的子查询(就是有多个查询字段) 示例:查询工作和工资等于“jack”的人的记录
SELECT
*
FROM
employee
WHERE
( job, sal ) = ( SELECT job, sal FROM employee WHERE ename = "jack" );
3、返回结果为单列多行的子查询(就是一个查询字段,有多个值的情况),对于这种情况,在WHERE子句中就可以使用IN,ANY,ALL,EXISTS等关键字。 示例:查找部门编号小于30的员工信息
SELECT
*
FROM
emp
WHERE
deptno IN ( SELECT deptno FROM dept WHERE deptno < 30 );
3.2 FROM子句后使用子查询
FROM子句后的子查询返回的结果为多行多列的数据记录,就类似一个虚拟的表,可以使用该种方式实现多表查询。
有了子查询,由于想要得到的数据时位于两个表中,所以我们还是需要使用连接来使两个表建立新的关系,只要连接,就一定是先对两个表做笛卡尔积操作。但有了子查询,我们可以将另一张表中需要的数据通过子查询的方式先查出来,然后再通过连接将结果和另一个表中的结果根据连接条件组合在一起,由于连接之前先做了一次查询,查询的结果只是符合要求的数据记录,而不是所有的,这样其实就减少了连接时表的数据记录。这样一来,笛卡尔积时的数据记录就会大大减少。
示例:查找部门编号为10,且工资大于2000的员工编号和员工姓名
SELECT
empno,
ename
FROM
emp
JOIN ( SELECT * FROM dept WHERE deptno = "10" ) dept ON emp.deptno = dept.deptno;
4 总结
1、多表连接,其实就是两个或两个以上的表进行连接行成一个新的关系表,然后再按照操作单表时的方法来操作这个新的关系表。
2、多表连接时,如果使用子查询的方式,可以先将多余的数据剔除,行成我们想要的数据表(可以理解成是一个虚拟表),然后再进行连接,能够提高表连接时的效率。
3、多表连接,本质上最后还是单表操作,所以单表操作查询语句一定要掌握透彻,不管多么复杂的多表连接SQL语句,先分清外层查询是什么,再看嵌套的子查询是什么。
|