全程软件测试(八十二):MySQL之多表连接查询&子查询—读书笔记

多表连接查询

1.交叉连接查询

交叉连接返回的结果是被连接的两个表中所有数据行的笛卡儿积;比如:集合A={a,b},集合B={0,1,2},则集合A和B的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。所以,交叉连接也被称为笛卡尔连接,其语法格式如下:

SELECT * FROM1 CROSS JOIN2;

在该语法中:CROSS JOIN用于连接两个要查询的表,通过该语句可以查询两个表中所有的数据组合。

由于这个交叉连接查询在实际运用中没有任何意义,所以只做为了解即可

2.内连接查询

内连接(Inner Join)又称简单连接或自然连接,是一种非常常见的连接查询。内连接使用比较运算符对两个表中的数据进行比较并列出与连接条件匹配的数据行,组合成新的记录。也就是说在内连接查询中只有满足条件的记录才能出现在查询结果中。其语法格式如下:

SELECT 查询字段1,查询字段2, ... FROM1 [INNER] JOIN2 ON1.关系字段=表2.关系字段

在该语法中:INNER JOIN用于连接两个表,ON来指定连接条件;其中INNER可以省略。

准备数据,代码如下:

-- 若存在数据库mydb则删除DROP DATABASE IF EXISTS mydb;-- 创建数据库mydbCREATE DATABASE mydb;-- 选择数据库mydbUSE mydb;-- 创建部门表CREATE TABLE department(  did int (4) NOT NULL PRIMARY KEY,   dname varchar(20));-- 创建员工表CREATE TABLE employee (  eid int (4) NOT NULL PRIMARY KEY,   ename varchar (20),   eage int (2),   departmentid int (4) NOT NULL);-- 向部门表插入数据INSERT INTO department VALUES(1001,'财务部');INSERT INTO department VALUES(1002,'技术部');INSERT INTO department VALUES(1003,'行政部');INSERT INTO department VALUES(1004,'生活部');-- 向员工表插入数据INSERT INTO employee VALUES(1,'张三',19,1003);INSERT INTO employee VALUES(2,'李四',18,1002);INSERT INTO employee VALUES(3,'王五',20,1001);INSERT INTO employee VALUES(4,'赵六',20,1004);
  • 查询员工姓名及其所属部门名称 MySQL命令:
  • select employee.ename,department.dname from department inner join employee on department.did=employee.departmentid;

    运行效果展示

    3.外连接查询

    使用内连接查询时我们发现:返回的结果只包含符合查询条件和连接条件的数据。但是,有时还需要在返回查询结果中不仅包含符合条件的数据,而且还包括左表、右表或两个表中的所有数据,此时我们就需要使用外连接查询。外连接又分为左(外)连接和右(外)连接。其语法格式如下:

    SELECT 查询字段1,查询字段2, ... FROM1 LEFT | RIGHT [OUTER] JOIN2 ON1.关系字段=表2.关系字段 WHERE 条件

    由此可见,外连接的语法格式和内连接非常相似,只不过使用的是LEFT [OUTER] JOIN、RIGHT [OUTER] JOIN关键字。其中,关键字左边的表被称为左表,关键字右边的表被称为右表;OUTER可以省略。

    在使用左(外)连接和右(外)连接查询时,查询结果是不一致的,具体如下:

    1. LEFT [OUTER] JOIN 左(外)连接:返回包括左表中的所有记录和右表中符合连接条件的记录。(左表中的所有数据及两个表中共有的数据)
    2. RIGHT [OUTER] JOIN 右(外)连接:返回包括右表中的所有记录和左表中符合连接条件的记录。(右表中的所有数据及两个表中共有的数据)

    先准备数据,代码如下:

    -- 若存在数据库mydb则删除DROP DATABASE IF EXISTS mydb;-- 创建数据库mydbCREATE DATABASE mydb;-- 选择数据库mydbUSE mydb;-- 创建班级表CREATE TABLE class(  cid int (4) NOT NULL PRIMARY KEY,   cname varchar(20));-- 创建学生表CREATE TABLE student (  sid int (4) NOT NULL PRIMARY KEY,   sname varchar (20),   sage int (2),   classid int (4) NOT NULL);-- 向班级表插入数据INSERT INTO class VALUES(1001,'Java');INSERT INTO class VALUES(1002,'C++');INSERT INTO class VALUES(1003,'Python');INSERT INTO class VALUES(1004,'PHP');-- 向学生表插入数据INSERT INTO student VALUES(1,'张三',20,1001);INSERT INTO student VALUES(2,'李四',21,1002);INSERT INTO student VALUES(3,'王五',24,1002);INSERT INTO student VALUES(4,'赵六',23,1003);INSERT INTO student VALUES(5,'Jack',22,1009);

    准备这组数据有一定的特点,为的是让大家直观的看出左连接与右连接的不同之处

    1. 班级编 为1004的PHP班级没有学生
    2. 学 为5的学生Jack班级编 为1009,该班级编 并不在班级表中

    3.1 左(外)连接查询

    左(外)连接的结果包括LEFT JOIN子句中指定的左表的所有记录,以及所有满足连接条件的记录。如果左表的某条记录在右表中不存在则在右表中显示为空。

  • 查询每个班的班级ID、班级名称及该班的所有学生的名字 MySQL命令:
  • select class.cid,class.cname,student.sname from class left outer join student on class.cid=student.classid;

    运行效果展示

    展示结果分析:

    1. 分别找出Java班、C++班、Python班的学生(公共部分)
    2. 右表的Jack不满足查询条件故其没有出现在查询结果中
    3. 虽然左表的PHP班没有学生,但是依然显示了PHP的信息;但是,它对应的学生名字为NULL(左表剩余部分)

    3.2 右(外)连接查询

    右(外)连接的结果包括RIGHT JOIN子句中指定的右表的所有记录,以及所有满足连接条件的记录。如果右表的某条记录在左表中没有匹配,则左表将返回空值。

  • 查询每个班的班级ID、班级名称及该班的所有学生的名字 MySQL命令:
  • select class.cid,class.cname,student.sname from class right outer join student on class.cid=student.classid;

    运行效果展示

    展示结果分析:

    1. 分别找出Java班、C++班、Python班的学生(公共部分)
    2. 左表的PHP班不满足查询条件故其没有出现在查询结果中
    3. 虽然右表的jack没有对应班级,但是任然显示王跃跃的信息;但是,它对应的班级以及班级编 均为NULL(右表剩余部分)

    子查询

    子查询是指一个查询语句嵌套在另一个查询语句内部的查询;该查询语句可以嵌套在一个 SELECT、SELECT…INTO、INSERT…INTO等语句中。在执行查询时,首先会执行子查询中的语句,再将返回的结果作为外层查询的过滤条件。在子査询中通常可以使用比较运算符和IN、EXISTS、ANY、ALL等关键字。

    准备数据,代码如下:

    DROP TABLE IF EXISTS student;DROP TABLE IF EXISTS class;-- 创建班级表CREATE TABLE class(  cid int (4) NOT NULL PRIMARY KEY,   cname varchar(20));-- 创建学生表CREATE TABLE student (  sid int (4) NOT NULL PRIMARY KEY,   sname varchar (20),   sage int (2),   classid int (4) NOT NULL);-- 向班级表插入数据INSERT INTO class VALUES(1001,'Java');INSERT INTO class VALUES(1002,'C++');INSERT INTO class VALUES(1003,'Python');INSERT INTO class VALUES(1004,'PHP');INSERT INTO class VALUES(1005,'Android');-- 向学生表插入数据INSERT INTO student VALUES(1,'张三',20,1001);INSERT INTO student VALUES(2,'李四',21,1002);INSERT INTO student VALUES(3,'王五',24,1003);INSERT INTO student VALUES(4,'赵六',23,1004);INSERT INTO student VALUES(5,'小明',21,1001);INSERT INTO student VALUES(6,'小红',26,1001);INSERT INTO student VALUES(7,'小亮',27,1002);

    1.带比较运算符的子查询

    比较运算符前面我们提到过,就是>、<、=、>=、<=、!=等

  • 查询张三同学所在班级的信息 MySQL命令:
  • select * from class where cid=(select classid from student where sname='张三');

    运行效果展示

  • 查询比张三同学所在班级编 还大的班级的信息 MySQL命令:
  • select * from class where cid>(select classid from student where sname='张三');

    运行效果展示

    2.带EXISTS关键字的子查询

    EXISTS关键字后面的参数可以是任意一个子查询, 它不产生任何数据只返回TRUE或FALSE。当返回值为TRUE时外层查询才会执行

  • 假如王五同学在学生表中则从班级表查询所有班级信息 MySQL命令:
  • select * from class where exists (select * from student where sname='王五');

    运行效果展示

    3.带ANY关键字的子查询

    ANY关键字表示满足其中任意一个条件就返回一个结果作为外层查询条件。

  • 查询比任一学生所属班级 还大的班级编 MySQL命令:
  • select * from class where cid > any (select classid from student);

    运行效果展示

    4.带ALL关键字的子查询

    ALL关键字与ANY有点类似,只不过带ALL关键字的子査询返回的结果需同时满足所有内层査询条件。

  • 查询比所有学生所属班级 还大的班级编 MySQL命令:
  • select * from class where cid > all (select classid from student);

    运行效果展示

    重要(从关键字分析):

    查询语句的书写顺序和执行顺序

    select ===> from ===> where ===> group by ===> having ===> order by ===> limit

    查询语句的执行顺序

    from ===> where ===> group by ===> having ===> select ===> order by ===> limit

    声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

    上一篇 2021年11月15日
    下一篇 2021年11月15日

    相关推荐