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)
通常情况下,内连接能够查询出来的数据,使用子查询也能查询出来
MySQL之多表查询(笛卡尔积查询、内连接、外连接(左外连接,右外连接)、union、union all )的更多相关文章
- MySQL对数据表进行分组查询
MySQL对数据表进行分组查询(GROUP BY) GROUP BY关键字可以将查询结果按照某个字段或多个字段进行分组.字段中值相等的为一组.基本的语法格式如下: GROUP BY 属性名 [HAVI ...
- MySQL对数据表进行分组查询(GROUP BY)
MySQL对数据表进行分组查询(GROUP BY) GROUP BY关键字可以将查询结果按照某个字段或多个字段进行分组.字段中值相等的为一组.基本的语法格式如下: GROUP BY 属性名 [HAVI ...
- 在查询用户的权限的时候 使用左外连接 和 access数据库中左外连接
一般做视图最好是做成左外连接的.而其作用尤其在我们查询用户当前的权限时尤为明显,我们将 权限表即模块表放→角色权限表→角色表→用户角色表→用户表 就这样left outer join 连接起来,这样就 ...
- Database学习 - mysql 数据库 多表/复合/子 查询
多表查询 多表查询,基本规则,通过两表有关联字段的进行条件匹配查询 内连接查询 方式一: SELECT 查看字段名[,查看字段名] FROM 一表名,二表名 WHERE 一/二表.字段 = 一/二表. ...
- MYSQL优化派生表(子查询)在From语句中的
Mysql 在5.6.3中,优化器更有效率地处理派生表(在from语句中的子查询): 优化器推迟物化子查询在from语句中的子查询,知道子查询的内容在查询正真执行需要时,才开始物化.这一举措提高了性能 ...
- MySQL:习题(单表多条件查询二)
Sutdent表的定义 字段名 字段描述 数据类型 主键 外键 非空 唯一 自增 Id 学号 INT(10) 是 否 是 是 是 Name 姓名 VARCHAR(20) 否 否 是 否 否 Sex 性 ...
- mysql 数据库或者表空间使用查询
直接上语句 查所有数据库占用空间大小 select TABLE_SCHEMA, concat(truncate(sum(data_length)/1024/1024,2),' MB') as data ...
- mysql 遍历所有表并条件查询
use eepm_push; DROP PROCEDURE IF EXISTS FountTable; delimiter $$ create procedure FountTable() begin ...
- SQL: 左连接,右连接,内连接,左外连接,右外连接,完全连接
例子: ---------------------- --------------------------- a表 id name b表 id job parent_id 1 张三 ...
随机推荐
- 【 Struts2 过滤器】
LoginInterceptor package k.util; import com.opensymphony.xwork2.ActionInvocation; import com.opensym ...
- linux shell date的用法
该随笔引用自https://www.cnblogs.com/alsodzy/p/8403870.html 在 linux shell 里面date命令的参数 %% 一个文字的 % %a 当前local ...
- 【C语言】创建一个函数,利用该函数将两个字符串连接起来
代码: #include<stdio.h> ], ]) { int i, j; ; c[i] != '\0'; i++); ; d[j] != '\0'; j++) { c[i++] = ...
- DIV 设置垂直居中
要说面试官经常问的问题中“如何将一个块元素水平垂直居中”就算一个. 之前的面试中也有中招,现在总结一下. 1.CSS垂直水平居中 要让DIV水平和垂直居中,必需知道该DIV得宽度和高度,然后设置位置为 ...
- Java_Habse_shell
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.*; import org.apache.had ...
- anacondaPython3.7退回到Python3.6
https://blog.csdn.net/Fhujinwu/article/details/85851587
- mongodb 用户指引
维护人:陈权 一.mongodb install on linuxcurl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.6 ...
- HIS读书笔记
医院的主要信息子系统,包括医院信息管理系统HIMS,放射科信息系统RIS,图像存档与传输系统PACS,检验信息系统LIS,医学信息传输标准与系统集成,以及临床路径和电子病历等. 医院信息系统一般划分为 ...
- Spark Streaming实践和优化
发表于:<程序员>杂志2016年2月刊.链接:http://geek.csdn.net/news/detail/54500 作者:徐鑫,董西成 在流式计算领域,Spark Streamin ...
- cmd添加管理员账号
net user 用户名 密码 /add net localgroup Administrators 用户名 /add