mysql内外连接_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 |

+------+--------+------+--------+------+---------+

总结:

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

解决办法: select *from dept,emp where dept.id = dept_id;

同时笛卡尔积的结果,会产生重复的字段信息

解决办法: 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)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值