一、多表查询

在实际开发中,大部分情况下都不是从单表中查询数据,一般都是多张表联合查询取出最终的结果。一般一个业务都会对应多张表。

1.表的连接方式的分类

内连接:等值连接、非等值连接、自连接

外连接:左外连接(又称左连接)、右外连接(又称右连接)

全连接:(很少用,不介绍)

2.笛卡尔积连接

示例:

员工表emp(员工编号EMPNO,员工姓名ENAME,员工职位JOB,MGR上级领导编号,入职时间HIREDATE,工资SAL,津贴COMM,所属部门编号DEPTNO):

mysql 一次性 联查2张表 mysql查询2个表_数据库


部门表dept(部门编号DEPTNO,部门名称DNAME,部门位置LOC):

mysql 一次性 联查2张表 mysql查询2个表_mysql 一次性 联查2张表_02


select ename,dname from emp,dept;

上述sql语句emp表与dept表进行笛卡尔积连接,结果为56条记录(4*14)。

表的别名

select e.ename,d.dname from emp e,dept d;//emp表的别名为e,dept表的别名为d,使用表的别名是为了在select时区分不同表的同名字段

3.避免笛卡尔积现象

避免笛卡尔积现象的方法是加条件进行过滤,但是要注意,加条件进行过滤不会减少记录的匹配次数,只不过显示的是有效记录(即最开始的连接还是笛卡尔积连接,再在笛卡尔积连接的基础上进行过滤)。

mysql 一次性 联查2张表 mysql查询2个表_数据库_03


说明:上述sql语法是sql92版本,现在很少使用。

4.内连接之等值连接

最大的特点是条件是等值关系。

语法:… <表A > join <表B> on <连接条件> where …(sql99语法)

示例:

mysql 一次性 联查2张表 mysql查询2个表_子查询_04


上例中的sql语句也可以写为:select e.ename,d.dname from emp e join dept d on e.depton = d.deptno;

说明:(1)shang述sql语句省略了inner,即“select e.ename,d.dname from emp e join dept d on e.depton = d.deptno;”等价于“select e.ename,d.dname from emp e innner join dept d on e.depton = d.deptno;"。

(2)可以看出sql99语法的结构更清晰,把“表的连接条件”与“连接后的筛选条件(where)”区分开。

5.内连接之非等值连接

特点是连接条件是非等量关系。

工资等级表salgrade(GRADE工资等级,LOSAL该等级工资下限,HISAL该等级工资上限):

mysql 一次性 联查2张表 mysql查询2个表_mysql_05


员工表emp(员工编号EMPNO,员工姓名ENAME,员工职位JOB,MGR,入职时间HIREDATE,工资SAL,津贴COMM,所属部门编号DEPTNO):

mysql 一次性 联查2张表 mysql查询2个表_sql_06


mysql 一次性 联查2张表 mysql查询2个表_mysql_07


实现的sql语句为:

mysql 一次性 联查2张表 mysql查询2个表_sql_08


可以看出非等值连接就是连接条件不为等式的内连接。

6.内连接之自连接

特点是一张表看作两张表,自己连自己。

示例:

员工表emp(员工编号EMPNO,员工姓名ENAME,员工职位JOB,MGR上级领导编号,入职时间HIREDATE,工资SAL,津贴COMM,所属部门编号DEPTNO):

mysql 一次性 联查2张表 mysql查询2个表_sql_09


mysql 一次性 联查2张表 mysql查询2个表_数据库_10


mysql 一次性 联查2张表 mysql查询2个表_数据库_11


总结:可以看出,自连接适用于一个表的两个字段属于同一类,两个字段之间具有一定的关联,这种关联有些类似于表之间的外键。

7.外连接

内连接:表A和表B进行连接,使用内连接,凡是A表与B表能够匹配上的记录查询出来,A、B两张表没有主副之分,两张表是平等的。

外连接:假设A和B进行连接,使用外连接,A、B两张表中有一张是主表,有一张是副表。主要查询主表中的数据,另外带上查询副表。当副表中的数据没有和主表中的数据匹配上,副表自动模拟出null与之匹配。即外连接的特点是主表的数据无条件的全部查询出来。

左外连接(左连接):表示左边的表是主表。

右外连接(右连接):表示右边的表是主表。

mysql 一次性 联查2张表 mysql查询2个表_mysql 一次性 联查2张表_12


可以看出,如果使用内连接的自连接,上图中的empno为7839的记录会被去除,因为mgr无法匹配。这里需要使用外连接。

使用左外连接:

mysql 一次性 联查2张表 mysql查询2个表_mysql_13


等价于:

mysql 一次性 联查2张表 mysql查询2个表_sql_14


说明:任何一个左外连接都有一个对应的右外连接写法。left和right后省略了outer,outer可写可不写。

8.三张以上表连接查询

案例:找出每一个员工的部门名称以及工资等级。

员工表emp(员工编号EMPNO,员工姓名ENAME,工资SAL,所属部门编号DEPTNO)

mysql 一次性 联查2张表 mysql查询2个表_子查询_15


部门表dept:

mysql 一次性 联查2张表 mysql查询2个表_子查询_16


工资等级表salgrade(GRADE工资等级,LOSAL该等级工资下限,HISAL该等级工资上限):

mysql 一次性 联查2张表 mysql查询2个表_mysql_17


执行的sql语句为:

mysql 一次性 联查2张表 mysql查询2个表_子查询_18


再例:

mysql 一次性 联查2张表 mysql查询2个表_mysql_19


二、子查询(这里举的例子参考上面例子中出现的表)

子查询就是select语句中嵌套了select语句,被嵌套的select语句是子查询。子查询可以出现的位置:

select …<select子句>

from …<select子句>

where …<select子句>

1.where后嵌套select语句

员工表emp(员工编号EMPNO,员工姓名ENAME,工资SAL,所属部门编号DEPTNO)

mysql 一次性 联查2张表 mysql查询2个表_mysql_20


mysql 一次性 联查2张表 mysql查询2个表_mysql_21


使用子查询:

mysql 一次性 联查2张表 mysql查询2个表_子查询_22


2.from后嵌套select子查询

员工表emp(员工编号EMPNO,员工姓名ENAME,工资SAL,所属部门编号DEPTNO)

mysql 一次性 联查2张表 mysql查询2个表_sql_23


工资等级表salgrade(GRADE工资等级,LOSAL该等级工资下限,HISAL该等级工资上限):

mysql 一次性 联查2张表 mysql查询2个表_mysql_24


mysql 一次性 联查2张表 mysql查询2个表_数据库_25


使用嵌套子查询:

mysql 一次性 联查2张表 mysql查询2个表_子查询_26


3.select后嵌套子查询

mysql 一次性 联查2张表 mysql查询2个表_mysql_27


另一种方式是在select后嵌套子查询(能看懂就行):

mysql 一次性 联查2张表 mysql查询2个表_数据库_28


解释:如果内层子查询不依赖外层子查询,称为不相关嵌套查询,可由内向外逐层处理,也就是每个内层子查询在上一层查询处理之前求解,内层子查询的结果用于建立其外层查询。如果内层查询依赖于外层查询称为相关嵌套查询,对于外层查询结果的每一行根据它与内层查村相关的列值处理内层查询。

三、union(将查询结果集相加)

mysql 一次性 联查2张表 mysql查询2个表_子查询_29


mysql 一次性 联查2张表 mysql查询2个表_mysql 一次性 联查2张表_30


注意:union的结果union前面的子句的查询结果排在前面,union后面的子句的查询结果排在后面。

除此之外,unon可以处理or和in子句不能处理的情况,即将两张不相关的表的查询结果拼在一起:

mysql 一次性 联查2张表 mysql查询2个表_mysql_31


注意:union连接的两个查询结果的列数需相同。

四、limit(limit是mysql特有的,其他数据库中没有,不通用;Oracle中有一个相同的机制,叫做rownum)

limit机制很重要,是分页机制的基础。

limit取结果集中的部分数据。

语法机制:limit startIndex, length

startIndex表示起始位置,length表示取几个。如果只写了一个数字,则表示length,startIndex默认为0。

mysql 一次性 联查2张表 mysql查询2个表_mysql 一次性 联查2张表_32


注意:limit是select语句最后执行(在order by之后)的环节。