前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL 的 Full Join 的实现

MySQL 的 Full Join 的实现

作者头像
白日梦想家
发布2020-07-18 18:33:58
10.7K0
发布2020-07-18 18:33:58
举报
文章被收录于专栏:SQL实现SQL实现

截止当前最新版本 8.0.19,MySQL 尚未支持 Full Join(全外连接),但我们可以使用其它方式实现 Full Join 的效果。

理论上,全外连接是左外连接和右外连接的组合。完整的外部连接包括联接表中的所有行,无论另一个表是否具有匹配的行。

如果联接表中的行不匹配,则全外连接的结果集将为缺少匹配行的表的每一列设置为 NULL 。对于匹配的行,返回它们关联的结果。

我们来看在其它支持 Full Join 语法的关系数据库的执行情况,有示例表 empdept (这两个表的表结构及数据放在文末)。经过观察,我们可知 emp 表的 7259 编号的员工缺少部门编号,dept 表中编号为 40 的部门在 emp 表中没有对应记录。

图 1 emp 表

图 2 dept 表

执行下面的 SQL 脚本,输出图 3 的结果。

代码语言:javascript
复制
SELECT   * FROM  emp e FULL   JOIN dept d     ON d.deptno = e.deptno

注意,这段 SQL 放到 MySQL 里是无法执行。

图 3 全连接的输出结果

在 MySQL 里,我们通过以下两种方式实现 Full Join 的效果。当然了,还有其它方式也可以实现这效果,就不一一列举了。

方式一:两个 Join 和一个 Union

代码语言:javascript
复制
SELECT   * FROM  emp e   LEFT JOIN dept d     ON d.deptno = e.deptno UNIONSELECT   * FROM  emp e   RIGHT JOIN dept d     ON d.deptno = e.deptno

在这种情况下,这可以提供理想的结果,但并非在所有情况下都正确。

如果 emp 表或者 dept 表存在重复记录,使用这种方式将会移除重复记录。下面我们将通过 UNION ALL 改写这段 SQL,使之完全达到 FULL JOIN 的效果。

方式二:UNION ALL 和排除联接

代码语言:javascript
复制
SELECT   * FROM  emp e   LEFT JOIN dept d     ON d.deptno = e.deptno UNION ALL SELECT   * FROM  emp e   RIGHT JOIN dept d     ON d.deptno = e.deptno WHERE e.deptno IS NULL

这样可以保留同一个表中重复的行,并且保证两个子查询不会产生重复记录。

由于不需要排序和删除重复项,因此对于大型结果集,这可能会大大提高效率。

结语

在工作中,我们用到 full join 的场景可能比较少。那么在什么时候你会想到使用 full join呢?

附上文中用到的表的数据脚本

代码语言:javascript
复制
DROP TABLE IF EXISTS emp;
CREATE TABLE emp (  empno INT NOT NULL,  ename VARCHAR(10) DEFAULT NULL,  job VARCHAR(9) DEFAULT NULL,  mgr INT DEFAULT NULL,  hiredate DATE DEFAULT NULL,  sal DECIMAL(7,2) DEFAULT NULL,  comm DECIMAL(7,2) DEFAULT NULL,  deptno INT DEFAULT NULL);
DROP TABLE IF EXISTS dept;
CREATE TABLE dept (  deptno INT DEFAULT NULL,  dname VARCHAR(14) DEFAULT NULL,  loc VARCHAR(13) DEFAULT NULL);
INSERT INTO emp VALUES (7369,'SMITH','CLERK',7902,'1980-12-17','800.00',NULL,20);INSERT INTO emp VALUES (7499,'ALLEN','SALESMAN',7698,'1981-02-20','1600.00','300.00',30);INSERT INTO emp VALUES (7521,'WARD','SALESMAN',7698,'1981-02-22','1250.00','500.00',30);INSERT INTO emp VALUES (7566,'JONES','MANAGER',7839,'1981-04-02','2975.00',NULL,20);INSERT INTO emp VALUES (7654,'MARTIN','SALESMAN',7698,'1981-09-28','1250.00','1400.00',30);INSERT INTO emp VALUES (7698,'BLAKE','MANAGER',7839,'1981-05-01','2850.00',NULL,30);INSERT INTO emp VALUES (7782,'CLARK','MANAGER',7839,'1981-06-09','2450.00',NULL,10);INSERT INTO emp VALUES (7788,'SCOTT','ANALYST',7566,'1982-12-09','3000.00',NULL,20);INSERT INTO emp VALUES (7839,'KING','PRESIDENT',NULL,'1981-11-17','5000.00',NULL,10);INSERT INTO emp VALUES (7844,'TURNER','SALESMAN',7698,'1981-09-08','1500.00','0.00',30);INSERT INTO emp VALUES (7876,'ADAMS','CLERK',7788,'1983-01-12','1100.00',NULL,20);INSERT INTO emp VALUES (7900,'JAMES','CLERK',7698,'1981-12-03','950.00',NULL,30);INSERT INTO emp VALUES (7902,'FORD','ANALYST',7566,'1981-12-03','3000.00',NULL,20);INSERT INTO emp VALUES (7934,'MILLER','CLERK',7782,'1982-01-23','1300.00',NULL,10);INSERT INTO emp VALUES (7259,'ZHOUXX','MANAGER',7839,'1980-12-19','4800.00',NULL,NULL);
INSERT INTO dept VALUES (10,'ACCOUNTING','NEW YORK');INSERT INTO dept VALUES (20,'RESEARCH','DALLAS');INSERT INTO dept VALUES (30,'SALES','CHICAGO');INSERT INTO dept VALUES (40,'OPERATIONS','BOSTON');
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SQL实现 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 结语
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档