MySQL之多表查询(笛卡尔积查询、内连接、外连接(左外连接,右外连接)、union、union all )

多表查询
测试数据
create table emp (id int,name char(10),sex char,dept_id int);
insert emp values(1,"大黄","m",1);
insert emp values(2,"老王","m",2);
insert emp values(3,"老李","w",30);

#一张表示部门表
#存在一些没有员工的的部门

create table dept (id int,name char(10));
insert dept values(1,"市场");
insert dept values(2,"财务");
insert dept values(3,"行政");
1. 笛卡尔积查询
# 笛卡尔积查询,
mysql> select *from dept,emp;
+------+--------+------+--------+------+---------+
| id   | name   | id   | name   | sex  | dept_id |
+------+--------+------+--------+------+---------+
|    1 | 市场   |    1 | 大黄   | m    |       1 |
|    2 | 财务   |    1 | 大黄   | m    |       1 |
|    3 | 行政   |    1 | 大黄   | m    |       1 |
|    1 | 市场   |    2 | 老王   | m    |       2 |
|    2 | 财务   |    2 | 老王   | m    |       2 |
|    3 | 行政   |    2 | 老王   | m    |       2 |
|    1 | 市场   |    3 | 老李   | w    |      30 |
|    2 | 财务   |    3 | 老李   | w    |      30 |
|    3 | 行政   |    3 | 老李   | w    |      30 |
+------+--------+------+--------+------+---------+
9 rows in set (0.00 sec)



# 改进版
mysql> select *from dept,emp where dept.id = dept_id;
+------+--------+------+--------+------+---------+
| id   | name   | id   | name   | sex  | dept_id |
+------+--------+------+--------+------+---------+
|    1 | 市场   |    1 | 大黄   | m    |       1 |
|    2 | 财务   |    2 | 老王   | m    |       2 |
+------+--------+------+--------+------+---------+

总结:

  1. 笛卡尔积查询的结果,存在很多错误的数据。即数据关联关系错误

    解决办法:

    select *from dept,emp where dept.id = dept_id;
    
  2. 同时笛卡尔积的结果,会产生重复的字段信息

    解决办法:

    select 指定字段... from dept,emp where dept.id = dept_id;
    
2. 内连接

内连接查询本质上就是笛卡尔积查询

mysql> select *from dept join emp ;
+------+--------+------+--------+------+---------+
| id   | name   | id   | name   | sex  | dept_id |
+------+--------+------+--------+------+---------+
|    1 | 市场   |    1 | 大黄   | m    |       1 |
|    2 | 财务   |    1 | 大黄   | m    |       1 |
|    3 | 行政   |    1 | 大黄   | m    |       1 |
|    1 | 市场   |    2 | 老王   | m    |       2 |
|    2 | 财务   |    2 | 老王   | m    |       2 |
|    3 | 行政   |    2 | 老王   | m    |       2 |
|    1 | 市场   |    3 | 老李   | w    |      30 |
|    2 | 财务   |    3 | 老李   | w    |      30 |
|    3 | 行政   |    3 | 老李   | w    |      30 |
+------+--------+------+--------+------+---------+
9 rows in set (0.00 sec)

mysql> select *from dept join emp on dept.id=emp.dept_id;
+------+--------+------+--------+------+---------+
| id   | name   | id   | name   | sex  | dept_id |
+------+--------+------+--------+------+---------+
|    1 | 市场   |    1 | 大黄   | m    |       1 |
|    2 | 财务   |    2 | 老王   | m    |       2 |
+------+--------+------+--------+------+---------+
2 rows in set (0.00 sec)
3. 外连接:左连接

左边的表无论是否能够匹配 都要完整显示,右边即使没有也要显示出来

# 需求:要查询所有员工以及所属的部门信息
mysql> select * from emp left join dept on dept_id= dept.id;
+------+--------+------+---------+------+--------+
| id   | name   | sex  | dept_id | id   | name   |
+------+--------+------+---------+------+--------+
|    1 | 大黄   | m    |       1 |    1 | 市场   |
|    2 | 老王   | m    |       2 |    2 | 财务   |
|    3 | 老李   | w    |      30 | NULL | NULL   |
+------+--------+------+---------+------+--------+
3 rows in set (0.00 sec)

# 注意 在外连接查询中 不能使用where关键字,必须使用on 专门来做表的对应关系


4. 外连接:右连接

右边的表无论是否能够匹配 都要完整显示,左边即使没有也要显示出来

select *from dept full join emp on dept.id = emp.dept_id; 
5. 外连接:全连接(不支持)

无论是否匹配成功,两边表的数据都要全显示

##mysql 不支持
select *from dept full join emp on dept.id = emp.dept_id; 


# 可以转化一种思路,使用左连接 + 右连接
select *from dept left join emp on dept.id=emp.dept_id
union
select *from dept right join emp on dept.id=emp.dept_id;
6. union:联合两个表

过滤重复,即重复的数据不显示。同时必须保证 两个表的列数要相同

select * from emp
union
select * from emp;


mysql> select * from emp
    -> union
    -> select * from emp;
+------+--------+------+---------+
| id   | name   | sex  | dept_id |
+------+--------+------+---------+
|    1 | 大黄   | m    |       1 |
|    2 | 老王   | m    |       2 |
|    3 | 老李   | w    |      30 |
+------+--------+------+---------+
3 rows in set (0.00 sec)
7. union all :

不过滤重复,即重复的数据可以显示。同时必须保证 两个表的列数要相同

select * from emp
union all
select * from emp;


mysql> select * from emp
    -> union all
    -> select * from emp;
+------+--------+------+---------+
| id   | name   | sex  | dept_id |
+------+--------+------+---------+
|    1 | 大黄   | m    |       1 |
|    2 | 老王   | m    |       2 |
|    3 | 老李   | w    |      30 |
|    1 | 大黄   | m    |       1 |
|    2 | 老王   | m    |       2 |
|    3 | 老李   | w    |      30 |
+------+--------+------+---------+
6 rows in set (0.00 sec)

总结:

内连接表示,只显示匹配成功的记录。一般情况下,我们通常使用内连接

外连接表示,没有匹配成功的也要显示

练习:

测试数据
create table stu(id int primary key auto_increment,name char(10));

create table tea(id int primary key auto_increment,name char(10));

create table tsr(id int primary key auto_increment,t_id int,s_id int,
foreign key(s_id) references stu(id),
foreign key(t_id) references tea(id));

insert into stu values(null,"张三"),(null,"李四");
insert into tea values(null,"egon"),(null,"wer");
insert into tsr values(null,1,1),(null,1,2),(null,2,2);


需求:查出egon教过的学生

使用内连接:

mysql> select  * from tea join tsr join  stu on tea.id=tsr.t_id  and tsr.s_id = stu.id  where tea.name="egon";
+----+------+----+------+------+----+--------+
| id | name | id | t_id | s_id | id | name   |
+----+------+----+------+------+----+--------+
|  1 | egon |  1 |    1 |    1 |  1 | 张三   |
|  1 | egon |  2 |    1 |    2 |  2 | 李四   |
+----+------+----+------+------+----+--------+
2 rows in set (0.00 sec)


mysql> select  stu.name from tea join tsr join  stu on tea.id=tsr.t_id  and tsr.s_id = stu.id  where tea.name="egon";
+--------+
| name   |
+--------+
| 张三   |
| 李四   |
+--------+
2 rows in set (0.00 sec)

使用子查询:

# 先查出egon对应的id
select id from tea where name="egon";

# 在tsr表中 查询 egon 教过学生 的id
select s_id from tsr where  t_id = (select id from tea where name="egon");

# 在学生表中查询出对应的id
select stu.name from stu where id in (select s_id from tsr where  t_id = (select id from tea where name="egon"));



mysql> select * from tea where name="egon";
+----+------+
| id | name |
+----+------+
|  1 | egon |
+----+------+
1 row in set (0.00 sec)


mysql> select s_id from tsr where  t_id = (select id from tea where name="egon");
+------+
| s_id |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)


mysql> select stu.name from stu where id in (select s_id from tsr where  t_id = (select id from tea where name="egon"));
+--------+
| name   |
+--------+
| 张三   |
| 李四   |
+--------+
2 rows in set (0.27 sec)

通常情况下,内连接能够查询出来的数据,使用子查询也能查询出来

posted @ 2019-07-15 16:53  Hello_Jack  阅读(4401)  评论(0编辑  收藏  举报
# 页脚html代码 /*头部导航栏*/ #navigator { font-size:15px; border-bottom: 1px solid #ededed; border-top: 1px solid #ededed; height: 60px;/*导航栏高度,原始50*/ clear: both; margin-top: 25px; } /*导航栏设置,可以自定义导航栏的目录*/ #navList { min-height: 35px; float: left; } #navList li { /*每一个栏目节点*/ float: left; margin: 0 5px 0 0; /*这里原来是0 40px 0 0 */ } #navList a { /*栏目文字的格式*/ display: block; width: 5em; height: 22px; float: left; text-align: center; padding-top: 19px; }