Mysql中嵌套查询和连接查询的区别

  • Post author:
  • Post category:mysql


一、嵌套查询

嵌套查询我们以mybatis中的嵌套查询举例:

1.1、创建数据库

CREATE TABLE `teacher` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
​
INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师'); 
​
CREATE TABLE `student` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  `tid` INT(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');


其中是n个学生对应1个老师

,因此pojo层的学生多了一个teacher属性,


按照查询嵌套处理:

<mapper namespace="com.dao.StudentMapper">
    <!--
        思路:
            1、查询所有的学生信息。
            2、根据查询出来的学生的tid,寻找对应的老师。即子查询。
    -->
    <select id="getStudents" resultMap="StudentTeacher">
        select * from student
    </select>
    
    <resultMap id="StudentTeacher" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <!--复杂的属性,我们需要单独处理。对象用association,集合用collection-->
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>
    
    <select id="getTeacher" resultType="Teacher">
        select * from teacher where id = #{id}
    </select>
</mapper>

注意:子查询效率低,原因是因为需要查询两次表格。


按照结果嵌套处理(推荐且常用)

<select id="getStudent2" resultMap="StudentTeacher2">
    select s.id sid,s.name sname,t.name tname
    from student s,teacher t
    where s.tid = t.id;
</select>
​
<resultMap id="StudentTeacher2" type="Student">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>


嵌套查询和嵌套结果区别:


嵌套查询:

1、嵌套查询是在查询SQL中嵌入一个子查询SQL;

2、嵌套查询会执行多条SQL语句;

3、查询效率低,要多查一轮


嵌套结果:

1、嵌套结果是一个嵌套的多表查询SQL;

2、嵌套结果只会执行一条复杂的SQL语句;

二、连接查询

2.1 内连接

关键字:

inner join……on

说明:组合两个表中的记录,返回关联字段符合查询条件的记录,也就是返回两个表的交集(阴影)部分。

select *
from table1 inner join table2
where table1.id = table2.id

2.2 左外连接

关键字:left outer join……on

说明:左(外)连接,左表(table1)的记录将会全部表示出来,而右表(table2)只会显示符合查询条件的记录。右表记录不足的地方均为NULL。或者:是指以左边的表的数据为基准,去匹配右边的表的数据,如果匹配到就显示,匹配不到就显示为null

SELECT t1.col1, t2.col2
FROM table1 t1 LEFT OUTER JOIN table2 t2 
ON t1.id = t2.id;

2.3 右外连接

和左外连接同理,不赘述

2.4 全外连接

顾名思义,把两张表的字段都查出来,没有对应的值就显示null,但是注意:MySql是没有全外连接的(MySql中没有full outer join关键字),想要达到全外连接的效果,可以使用union关键字连接左外连接和右外连接。

select e.empName,d.deptName
     FROM t_employee e 
     left JOIN t_dept d
     ON e.dept = d.id
UNION
select e.empName,d.deptName
     FROM t_employee e 
     RIGHT JOIN t_dept d
     ON e.dept = d.id;

UNION求两个结果集的并集,UNION连接的查询也较组合查询或符合查询。UNION会自动去除重复行,如果不喜欢去除重复行可以用UNION ALL。

2.5 自连接

自连接查询就是当前表与自身的连接查询,关键点在于虚拟化出一张表给一个别名

例如:查询员工以及他的上司的名称,由于上司也是员工,所以这里虚拟化出一张上司表

SELECT e.empName,b.empName
     from t_employee e LEFT JOIN t_employee b
     ON e.bossId = b.id;
​

三、嵌套查询和连接查询的区别

查询嵌套是利用子查询来实现多表对应,结果嵌套是利用一句复杂的sql语句来实现多表对应(下列对比以嵌套查询为例);而连接查询则是先对要查询的表进行笛卡尔积之后,筛选对比。


本人认为存在以下两种情况:


情况一

如果只是对应一个连接条件的话,两种查询都是一样的,效率无太多差距。但是相比于嵌套查询,连接查询的学习成本和使用体验会更加好。同时,连接查询可以通过调整主关联表,来先查询数据少的表,提高效率。


情况二:

如果存在多种连接的情况,比如多对一关系,我们可以使用嵌套查询来清晰的写出关系逻辑,对查询进行修改时,也会更加方便。在效率上,由于嵌套结果查询是直接执行一个复杂的sql语句来进行多表的查询,而虽然连接查询也是通过对多个表的查询,但它多出了一个使用笛卡尔积的过程,因此效率不如嵌套查询。

注意

:本文是作者通过查阅和学习网上资料整理,但并没找到真实书本依据,如有错误,本人虚心请教。



版权声明:本文为qq_56568435原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。