引言

实际业务开发中,往往会涉及到多张表之间的数据交互,这时候单表查询已经不能满足复杂的业务需求了,所以就需要用到多表的连接查询;

连接查询主要分为以下三种:

  • 内连接

    • 等值连接
    • 非等值连接
    • 自连接
  • 外连接
    • 左外连接
    • 右外连接
  • 全连接

其中常用的就是内连接和外连接,全连接用处很少,几乎不用,所以这里就不介绍了;

数据库表传送门

下面示例将会用到三张表:

emp员工表

+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
|  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
+-------+--------+-----------+------+------------+---------+---------+--------+

dept部门表:

+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+

salgrade工资等级表;

+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |
+-------+-------+-------+

笛卡尔积现象

相信很多人都听过这个概念,这是一个数学概念,大致意思是:

笛卡尔乘积是指在数学中,两个集合X和Y的笛卡尔积(Cartesian product),又称直积,
表示为 X * Y ,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员

在数据库中集合其实就是表,所以数据库中笛卡尔积现象可以这样解释:

笛卡尔积,又叫cross join,是SQL中两表连接的一种方式。
假如A表中的数据为m行,B表中的数据有n行,那么A和B做笛卡尔积,结果为 m * n 行

现在想要查询到每一个员工(ENAME)对应的部门名称(DNAME),那么就涉及到emp和dept两张表之间的查询,假如写了如下sql:

SELECT e.ENAME, d.DNAME
FROM emp e, dept d;

查询结果为:

+--------+------------+
| ENAME  | DNAME      |
+--------+------------+
| SMITH  | ACCOUNTING |
| SMITH  | RESEARCH   |
| SMITH  | SALES      |
| SMITH  | OPERATIONS |
| ALLEN  | ACCOUNTING |
| ALLEN  | RESEARCH   |
| ALLEN  | SALES      |
| ALLEN  | OPERATIONS |
...............等等一共56行
56 rows in set (0.00 sec)

可以发现查询结果并不符合要求,实际结果是emp表中每一行的数据都和dept表中所有数据进行了匹配,所以最后总行数为:

emp表行数(14)* dept表行数(4)

这就是笛卡尔积现象,出现这个现象的原因很简单,因为两个表的连接没有设置连接条件,所以没有连接条件的表关系返回的结果为笛卡尔积;

为了避免这个现象,可以使用WHERE子句建立连接关系:

SELECT e.ENAME, d.DNAME
FROM emp e, dept d
WHERE e.DEPTNO=d.DEPTNO;

查询结果为:

+--------+------------+
| ENAME  | DNAME      |
+--------+------------+
| SMITH  | RESEARCH   |
| ALLEN  | SALES      |
| WARD   | SALES      |
| JONES  | RESEARCH   |
| MARTIN | SALES      |
| BLAKE  | SALES      |
| CLARK  | ACCOUNTING |
| SCOTT  | RESEARCH   |
| KING   | ACCOUNTING |
| TURNER | SALES      |
| ADAMS  | RESEARCH   |
| JAMES  | SALES      |
| FORD   | RESEARCH   |
| MILLER | ACCOUNTING |
+--------+------------+
14 rows in set (0.00 sec)

这个结果也就是我们需要的结果了;

但是记住一点:虽然使用WHERE子句可以避免笛卡尔积现象,但是在查询过程中并不会减少匹配次数,只不过是把有效数据显示了出来

(意思是:使用了WHERE子句后,查询结果虽然只有14行,但是在查询过程中实际上是匹配了56次)

内连接

等值连接

上面使用的连接方法就是内连接中的等值连接,所以内连接是基于两个表之间的相等的测试,通俗来说就是两个表间的条件是等量关系

但是上面的那种语法已经过时了,那是92语法,现在一般使用的是99语法,一般需要使用INNER JOIN......ON连接两个表,所以上面的sql可以写为:

SELECT e.ENAME, d.DNAME
FROM emp e
INNER JOIN dept d
ON e.DEPTNO=d.DEPTNO;

结果是一样的;这里的INNER可以不写,默认就是内连接,但是写上可读性更好;

条件判断这里使用ON来判断,传递给ON的条件和传递给WHERE的条件是相同的;而且ON的后面还可以加WHERE判断语句a JOIN b ON 条件1 WHERE 条件2

非等值连接

非等值连接主要特点就是:连接条件中的关系是非等量关系

举个例子:找出每个员工的工资等级,要求显示员工名、工资、工资等级

这需要用到emp表和salgrade表,非常简单,只需要使用内连接连接这两个表,查询出在salgrade表中工资大于最低工资小于最高工资的等级即可;

SELECTe.ENAME,e.SAL,s.GRADE
FROMemp e
INNER JOINsalgrade s
ONe.SAL BETWEEN s.LOSAL AND s.HISAL;

查询结果:

+--------+---------+-------+
| ENAME  | SAL     | GRADE |
+--------+---------+-------+
| SMITH  |  800.00 |     1 |
| ALLEN  | 1600.00 |     3 |
| WARD   | 1250.00 |     2 |
| JONES  | 2975.00 |     4 |
| MARTIN | 1250.00 |     2 |
| BLAKE  | 2850.00 |     4 |
| CLARK  | 2450.00 |     4 |
| SCOTT  | 3000.00 |     4 |
| KING   | 5000.00 |     5 |
| TURNER | 1500.00 |     3 |
| ADAMS  | 1100.00 |     1 |
| JAMES  |  950.00 |     1 |
| FORD   | 3000.00 |     4 |
| MILLER | 1300.00 |     2 |
+--------+---------+-------+
14 rows in set (0.00 sec)

自连接

自连接有点特殊,它是基于一张表的查询,但是却把这一张表当成两张表来用;顾名思义就是自己连接自己;

下面用一个例子说明:找出每个员工的上级领导,要求显示员工名和对应的领导名

在员工表emp中每一个员工都有对应的上级(除了KING员工),所以可以把这一张表按不同的意思看成两张表:

员工表和上级表,看成哪个表那么其他部分就忽略不要在管了;

SELECTa.ENAME AS '员工',b.ENAME AS '领导'
FROMemp a
INNER JOINemp b
ONa.MGR = b.EMPNO;

约束条件就是让员工的领导编号等于领导的员工编号,这样把一个表当成了两个表来操作;

查询结果:

+--------+-------+
| 员工   | 领导  |
+--------+-------+
| SMITH  | FORD  |
| ALLEN  | BLAKE |
| WARD   | BLAKE |
| JONES  | KING  |
| MARTIN | BLAKE |
| BLAKE  | KING  |
| CLARK  | KING  |
| SCOTT  | JONES |
| TURNER | BLAKE |
| ADAMS  | SCOTT |
| JAMES  | BLAKE |
| FORD   | JONES |
| MILLER | CLARK |
+--------+-------+
13 rows in set (0.01 sec)

外连接

内连接在将一个表中的一行与另一个表中的行相关联时,会略过为空的行,就比如上面找员工领导的例子,KING是最大的领导,所以他没有领导,查询出来也没有它的数据,那么如何能带上它的数据呢?这就需要用到外连接;

外连接分为左外连接和右外连接,但是这两种连接方式并没有太大的区别,下面就一块来示范一下:

还是上面找员工领导的例子,这次额外要求把没有领导的员工也输出:

SELECTa.ENAME AS '员工',b.ENAME AS '领导'
FROMemp a
LEFT JOINemp b
ONa.MGR = b.EMPNO;

可以看到这里不再使用INNER JOIN内连接,而是换成了LEFT JOIN外连接,(等价于LEFT OUTER JOIN,OUTER可以忽略),意思是把LEFT JOIN左边的表作为主表,右边的表作为副表,这样的结果就是主表的所有内容都会查出来,而副表的内容依靠于主表内容;

查询结果:

+--------+-------+
| 员工   | 领导  |
+--------+-------+
| SMITH  | FORD  |
| ALLEN  | BLAKE |
| WARD   | BLAKE |
| JONES  | KING  |
| MARTIN | BLAKE |
| BLAKE  | KING  |
| CLARK  | KING  |
| SCOTT  | JONES |
| KING   | NULL  | 注意这里
| TURNER | BLAKE |
| ADAMS  | SCOTT |
| JAMES  | BLAKE |
| FORD   | JONES |
| MILLER | CLARK |
+--------+-------+
14 rows in set (0.00 sec)

可以看到副表没有的内容(KING)自动生成了NULL;

这就是左外连接,同样 右外连接(RIGHT JOIN) 就是右边的是主表,左边的是副表,那么这个查询也可以这样写:

SELECTa.ENAME AS '员工',b.ENAME AS '领导'
FROMemp b
RIGHT JOINemp a
ONa.MGR = b.EMPNO;

简单总结一下:

  • 主表在查询时占主导地位,主表的内容一定可以查出来;

  • 副表在查询时依附主表,若主表内容副表对应没有,则生成NULL;

总结

外连接有主表和副表之分,而内连接没有主副之分

在示例中只设计两张表的连接,而在连接多张表查询时也一样,比如 表一 JOIN 表二 ON 条件一 JOIN 表三 ON 条件二 JOIN 表四 ON 条件三......

实际业务会很复杂,所以要拆分开后再找表之间的关系,一步一步分析才行;


具体什么时候使用内连接什么时候使用外连接呢?只需要由外键区分即可:

  • 如果外键不能为空,优先使用内连接;
  • 如果外键可以为空:
    • 假如只需要查询那些在另一张表中有相对应的记录,使用内连接;
    • 假如需要查询左(右)侧表中所有符合条件的记录,使用左(右)外连接;

​ 注意:外键能不能为空是由数据库表设计时决定的,因为外键只是数据库表的一个字段,所以需要根据实际情况分析;

MySql连接查询——内连接与外连接相关推荐

  1. mysql连接查询(内联)_MySQL之连接查询

    JavaScript面向对象与原型 工厂模式:无法识别对象 function createObject(name, age) { //集中实例化的函数 var obj = new Object(); ...

  2. oracle 连接查询--内连接与外连接

    一.外连接 oracle 连接查询分为外链接和内连接,我们先看外连接[outer join].oracle 的外连接查询分为: 左外连接 (左边的表不加限制) left outer join: 右外连 ...

  3. mysql连接查询 内连接查询 外连接查询

    连接查询 连接查询是将两个或两个以上的表按照某个条件连接起来,从中选取需要的数据: t_book表: id bookName price author bookTypeId t_bookType表:  ...

  4. MySQL数据库连接查询(内连接)

    连接查询 1. 交叉连接(笛卡尔积)Cross Join 实例1.1:完成车辆表与线路表的交叉连接 代码如下: -- 1.1实现线路表与车辆表笛卡尔积 SELECT * FROM line CROSS ...

  5. 什么时候使用内连接,什么时候使用外连接

    需要查找两张表同时存在的数据,使用内连接  需要查找两张表中一张表存在,另一张表不存在的时候使用左外链接 或 右外链接  内连接的查询结果都是满足连接条件的元组.但有时我们也希望输出那些不满足连接条件 ...

  6. 内链接与外连接的区别

    两个表的连接,是通过将一个表中的一列或者多列同另一个表中的列链接而建立起来的.用来连接两张表的表达式组成了连接条件.当连接成功后,第二张表中的数据就同第一张表连接起来了,并形成了复合结果集--包括两张 ...

  7. 两表连接查询 mysql_MySQL 中两表连接查询总结

    在之前的学习中,筛选出来的列都是一张表中的,本篇开始是对连表查询的学习内容.先从以下场景开始: 生成一张报价单,报价单包含商品名称,栏目名称,商品库存,商品价格,栏目名称和商品信息放在两张表中. 传统 ...

  8. MySQL连接查询 内连接和外连接的区别

    MySQL 连接查询 @ sunRainAmazing 1.使用连接查询的场景 将多张表进行记录的连接查询(按照某个字段指定的条件进行数据的拼接):进行数据的拼接(两张表的内容显示在一个结果表中 使用 ...

  9. 4.mysql数据库创建,表中创建模具模板脚本,mysql_SQL99标准连接查询(恩,外部连接,全外连接,交叉连接)...

     mysql数据库创建,表创建模等模板脚本 -- 用root用户登录系统,运行脚本 -- 创建数据库 create database mydb61 character set utf8 ; -- ...

最新文章

  1. 使用plsql创建定时任务并执行
  2. StateListDrawable和ShapeDrawable结合使用
  3. ECShop 前台用户中心调整左侧栏目及中心部分呈现页面
  4. 新款ATM恶意软件Alice 可对抗动态分析 但目前需要物理接触主机
  5. Exceptionless 5.0.0本地Docker快速部署介绍
  6. 2021年上犹中学高考成绩查询入口,上犹县2019年高考成绩单出来了……
  7. 在GNS3中如何让NETFLOW能够捕获到流量
  8. 解决php保存文件时文件名乱码问题
  9. Oracle记录表删除操作简单方法
  10. ssh工具的使用(全平台运行)
  11. 如何将文件PDF格式转换成Word格式
  12. Android 应用中使用ContentObserver自动填写短信验证码
  13. 读书寄语:这一年,谢谢自己
  14. 相似矩阵、矩阵的相似对角化
  15. 对标阿里P7Android最全面试题合集(GitHub、掘金高赞收集)
  16. python菜鸟教程mac安装_Python菜鸟教程 | 多平台安装
  17. 小偷和抢劫是被怎么遏制的?
  18. DaVinci:HDR 调色
  19. linux修改vnc设置密码,更改root与vnc密码,配置vnc
  20. 完美解决丨 - [SyntaxError: invalid syntax](#SyntaxError-invalid-syntax)

热门文章

  1. [HMGCTF2022]wp
  2. 每天一个linux命令(31):echo命令
  3. AI可以拥有自我意识吗?、
  4. Linux操作系统管理
  5. eclipse中设置快捷键
  6. 微软,谷歌,苹果,Facebook,谁会是下一个XR巨头?
  7. 鲁大师10月新机性能榜:黑鲨4S Pro夺冠,天玑900成“团宠”?
  8. hibernate级联保存报空指针异常
  9. Mysql给普通和分页查询结果加序号
  10. IIS下配置 jsp