原创

【MySQL优化】- MySQL中join查询


在SQL执行过程中,使用太多的join回使性能下降,但由于设计和不得已的需求,不得不使用join,本篇文章将讲述join的七种方式以及其SQL的编写,通过实例来进行讲解

一、七种JOIN方式

连接可分为三类:

  1. 内连接(获取两个表中字段匹配关系的记录):join、inner join
  2. 外连接:left join、left outer join、right join、right outer join、union、union all
  3. 交叉连接:cross join

image-20210405180042600

  1. 内连接
select <select_list> from TableA A inner join TableB B on A.Key = B.Key
  1. 左连接
select <select_list> from TableA A left join TableB B on A.Key = B.Key
  1. 右连接
select <select_list> from TableA A right join TableB B on A.Key = B.Key
  1. 左连接
select <select_list> from TableA A left join TableB B on A.Key = B.Key where B.Key is NULL
  1. 右连接
select <select_list> from TableA A right join TableB B on A.Key = B.Key where A.Key is NULL
  1. 全连接
select <select_list> from TableA A full outer join TableB B on A.Key = B.Key
  1. 全连接
select <select_list> from TableA A full outer join TableB B on A.Key = B.Key where A.Key is NULL or B.Key is NULL

二、SQL编写

CREATE TABLE `tbl_dept` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`dept_name` VARCHAR(30) DEFAULT NULL,
`loc_add` VARCHAR(40) DEFAULT NULL,
PRIMARY KEY(`id`)
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT '部门表';

CREATE TABLE `tbl_emp` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(20) DEFAULT NULL,
`dept_id` INT(11) DEFAULT NULL ,
PRIMARY KEY(`id`)
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT '员工表';

INSERT INTO tbl_dept(dept_name,loc_add) VALUES('RD', 11);
INSERT INTO tbl_dept(dept_name,loc_add) VALUES('HR', 12);
INSERT INTO tbl_dept(dept_name,loc_add) VALUES('MK', 13);
INSERT INTO tbl_dept(dept_name,loc_add) VALUES('MIS', 14);
INSERT INTO tbl_dept(dept_name,loc_add) VALUES('FD', 15);

INSERT INTO tbl_emp(name, dept_id) VALUES('z3', 1);
INSERT INTO tbl_emp(name, dept_id) VALUES('z4', 1);
INSERT INTO tbl_emp(name, dept_id) VALUES('z5', 1);
INSERT INTO tbl_emp(name, dept_id) VALUES('w5', 2);
INSERT INTO tbl_emp(name, dept_id) VALUES('w6', 2);
INSERT INTO tbl_emp(name, dept_id) VALUES('s7', 3);
INSERT INTO tbl_emp(name, dept_id) VALUES('s8', 4);
INSERT INTO tbl_emp(name, dept_id) VALUES('s9', 51);

image-20210405232248918

image-20210405232310609

  1. 图中第一种情况,取A、B的交集,也就是查询部门表中id和员工表中部门id相同的交集,使用inner join即可
mysql> select * from tbl_emp a inner join tbl_dept b on a.dept_id = b.id;

image-20210405232417812

  1. 图中第二种情况,取A表的全部以及A和B公有的部分,也就是查询部门表和员工表公有的加上员工表独有的
mysql> select * from tbl_emp a left join tbl_dept b on a.dept_id = b.id;

image-20210405232841589

  1. 图中第三种情况,取B表的全部以及A和B公有的部分,也就是查询部门表和员工表公有的加上部门表独有的
mysql> select * from tbl_emp a right join tbl_dept b on a.dept_id = b.id;

image-20210405233941795

  1. 图中第四种情况,取A表独有的数据(排除了A、B的交集),也就是员工表独有的
mysql> select * from tbl_emp a left join tbl_dept b on a.dept_id = b.id where b.id is null;

image-20210405234736117

  1. 图中第五种情况,取B表独有的数据(排除A、B的交集),也就是部门表独有的
mysql> select * from tbl_emp a right join tbl_dept b on a.dept_id = b.id where a.dept_id is null;

image-20210405235336640

  1. 图中第六种情况,取A、B的并集,由于MySQL不支持full outer join,所以这里采用union来合并图二和图三的结果(union有去重效果)
mysql> select * from tbl_emp a left join tbl_dept b on a.dept_id = b.id 
    -> union
    -> select * from tbl_emp a right join tbl_dept b on a.dept_id = b.id;

image-20210405235915628

  1. 图中第七种情况,取A、B的差集,去掉公有部分,合并图四和图五的结果,还是使用union
mysql> select * from tbl_emp a left join tbl_dept b on a.dept_id = b.id where b.id is null
    -> union
    -> select * from tbl_emp a right join tbl_dept b on a.dept_id = b.id where a.dept_id is null;

image-20210406000643823

  • 作者:管理员(联系作者)
  • 发表时间:2022-05-03 10:22
  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 公众号转载:请在文末添加作者公众号二维码
  • 评论