MySQL数据库查询之多表查询总结


Posted in MySQL onAugust 05, 2022

多表关系

在进行数据库表结构的设计时,会根据业务的需求和业务模块之间的关系,分析设计表结构,由于业务之间相互关联,所以各个表结构之间也存在各种联系

表与表之间的联系:

1.一对多(多对一)

2.多对多

3.一对一

一对多(多对一)

例如,一个员工对应一个部门,一个部门可以对应多个员工

MySQL数据库查询之多表查询总结

一般在多的一方创建外键,指向一的那一方

员工与部门,在员工表上设置外键,指向部门表

多对多

例如,一个学生可以选修多门课程,一个课程可以被多名学生选修

一般会建立第三张表,至少包含两个外键,分别指向两张表的主键

MySQL数据库查询之多表查询总结

一对一

例如,用户和自己的学历信息的关系,一个人只对应一条学历信息

可以在任意一方加入外键,关联另一方的主键,并且设置外键为唯一(unique)

MySQL数据库查询之多表查询总结

注:可以放在一张表中,但是对其进行拆分,一张表放基础信息,另一张表放详情,可以提升操作效率

多表查询

概述:

从多张表中查询数据

笛卡尔积:

笛卡尔积为两个集合(两张表)中的每条数据进行两两组合的结果

在多表查询时会产生笛卡尔积,要通过添加条件消除笛卡尔积

MySQL数据库查询之多表查询总结

dept表:

MySQL数据库查询之多表查询总结

emp表:

MySQL数据库查询之多表查询总结

查询产生笛卡尔积的结果:

select * from emp, dept where emp.dept_id=dept.id;

MySQL数据库查询之多表查询总结

消除笛卡尔积(添加条件):

select * from emp, dept where emp.dept_id=dept.id;

MySQL数据库查询之多表查询总结

多表查询的分类

1.连接查询:

内连接:
    相当于查询AB的交集部分
外连接:
        左外连接:
            查询A的所有数据,同时拼接上B对应的数据
        右外连接:
            查询B的所有数据,同时拼接上A中对应的数据
自连接:
    表与自身连接查询
    自连接必须给表取别名

MySQL数据库查询之多表查询总结

2.子查询

数据准备

部门表:

MySQL数据库查询之多表查询总结

create table dept (
    id int auto_increment primary key comment 'id',
    name varchar(50) not null comment '部门名称'
) comment '部门表';

insert into dept (id, name)
values (1, '研发部'),
       (2, '市场部'),
       (3, '财务部'),
       (4, '销售部'),
       (5, '总经办'),
       (6, '人事部');

员工表:

MySQL数据库查询之多表查询总结

create table emp(
    id int auto_increment primary key ,
    name varchar(50) not null ,
    age int,
    job varchar(20) comment '职位',
    salary int ,
    entrydate date comment '入职时间',
    managerid int comment '直属领导id',
    dept_id int comment '所在部门id'
) comment '员工表';

insert into emp
values ( 1, '金庸', 66, '总裁', 20000, '2000-01-01', null, 5 ),
       ( 2, '张无忌', 20, '项目经理', 12500, '2005-12-05', 1, 1 ),
       ( 3, '杨晓', 33, '开发', 8400, '2000-11-03', 2, 1 ),
       ( 4, '韦一笑', 48, '开发', 11000, '2002-02-05', 2, 1 ),
       ( 5, '陈玉存', 43, '开发', 10500, '2004-09-07', 3, 1 ),
       ( 6, '小昭', 19, '程序员鼓励师', 6600, '2004-10-12', 2, 1 ),
       ( 7, '灭绝', 60, '财务总监', 8500, '2002-09-12', 1, 3 ),
       ( 8, '周芷若', 19, '会计', 48000, '2006-06-02', 7, 3 ),
       ( 9, '丁敏君', 23, '出纳', 5250, '2009-05-13', 7, 3 ),
       ( 10, '赵敏', 20, '市场部总监', 12500, '2004-10-12', 1, 2 ),
       ( 11, '鹿杖客', 56, '职员', 3750, '2006-10-03', 10, 2 ),
       ( 12, '何碧文', 19, '职员', 3750, '2007-05-09', 10, 2 ),
       ( 13, '东方白', 19, '职员', 5500, '2009-02-12', 10, 2 ),
       ( 14, '张三丰', 88, '销售总监', 14000, '2004-10-12', 1, 4 ),
       ( 15, '鱼梁洲', 38, '销售', 4600, '2004-10-12', 14, 4 ),
       ( 16, '宋远桥', 40, '销售', 4600, '2004-10-12', 14, 4 ),
       ( 17, '陈友谅', 42, null, 2000, '2011-10-12', 1, null );

内连接

语法:

# 隐式内连接
select 字段列表 from 表1,表2 where 条件;
# 显示内连接
select 字段列表 from 表1 [inner] join 表2 on 连接条件;

内连接查询的是两张表交集的部分

# 查询每一个员工的姓名及关联的部门的名称
select emp.name, dept.name from emp, dept where emp.dept_id=dept.id;
select emp.name, dept.name from emp inner join dept on emp.dept_id = dept.id;

外连接

语法:

# 左外连接
select 字段列表 from 表1 left [outer] join 表2 on 条件;
# 右外连接
select 字段列表 from 表1 right [outer] join 表2 on 条件;

左外连接相当于查询表1的所有数据包含表1和表2交集的部分数据

右外连接相当于查询表2的所有数据包含表1和表2交集部分的数据

# 查询emp表的所有数据,和应于的部门信息(左)
select emp.*, dept.* from emp left outer join dept on emp.dept_id = dept.id;
# 查询dept表的所有数据,和对于的员工信息(右)
select dept.*, emp.* from emp right outer join dept on emp.dept_id = dept.id;

左外连接和右外连接可以进行相互转化

自连接

语法:

select 字段列表 from 表a 别名a join 表a 别名b on 条件;

自链接查询可以是内连接查询也可以是外连接查询

# 查询员工及其所属领导的名字
# 自连接可以看成两张一样的表进行连接查询
select a.name, b.name from emp a join emp b on a.managerid=b.id;

联合查询

union、union all

对于联合查询就是把多次查询的结果合并起来,形成一个新的查询结果集

语法:

select 字段列表 from 表a
union [all]
select 字段列表 from 表b
# 将薪资低于5000的员工和年龄大于50的员工查询出来
select * from emp where salary>5000
union all
select * from emp where age>50;
# 没有all重复满足条件的只出现一次
# 将薪资低于5000的员工和年龄大于50的员工查询出来
select * from emp where salary>5000
union
select * from emp where age>50;

对于联合查询的多张表的列数必须保持一致,字段类型也要保持一致

union all会将全部的数据直接合并在一起,union会对合并之后的数据去重

子查询

概念:SQL语句中嵌套select语句为嵌套查询,又称子查询

select * from 表1 where 字段=(select 字段 from 表2);

子查询外的语句可以是insert、update、delete、select中的一个

根据子查询的结构不同,分为:

标量子查询:子查询的结果为单个值
列子查询:子查询的结果为一列
行子查询:子查询的结果为一行
表子查询:子查询的结果为多行多列

根据子查询的位置,分为:

where之后
from之后
select之后

标量子查询

子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式,这种子查询称为标量子查询
常用符号:=、<>、>、>=、<、<=

# 根据销售部门的id查询员工信息
# 先分开查询
# 查询销售部门的id
select id from dept where name='销售部'; #id为4
# 查询销售部门中员工的信息
select * from emp where dept_id=4;
# 合并为一个查询
select * from emp where dept_id=(select dept.id from dept where dept.name='销售部' );

列子查询

子查询的结果为一列(可以是多行)的,这种子查询为列子查询

常用操作符:

MySQL数据库查询之多表查询总结

# 列子查询
# 查询销售部和市场部的所有员工信息
# 查询销售部和市场部的id
select id from dept where name='销售部' or name='市场部'; #id为2 4
# 查询两个部门的所有员工
select * from emp where dept_id in (2,4);
# 合并
select * from emp where dept_id in (select id from dept where name='销售部' or name='市场部');

行子查询

子查询返回的结果是一行(可以是多列),这种子查询为行子查询

常用操作符:=、<>、in、not in

# 查询与张无忌的薪资及直属领导相同的员工信息
# 查询张无忌的薪资和直属领导
select salary, managerid from emp where name='张无忌';
# 查询与张无忌的薪资及直属领导相同的员工信息
select * from emp where (salary,managerid)=(select salary, managerid from emp where name='张无忌');

表子查询

子查询的结果是多行多列这种查询为表子查询

常用操作符:in

# 查询与鹿杖客和宋远桥的职位和薪资相同的员工信息
select * from emp where (job, salary) in ( select job, salary from emp where name in ('鹿杖客', '宋远桥'));

表子查询的子表作为临时表

# 查询入职日期是'2006-01-01‘之后的员工信息和部门信息
# 先查询出入职在'2006-01-01‘之后员工的所有信息
# 与部门表左连接
select e.*, dept.* from (select * from emp where entrydate>'2006-01-01') e left outer join dept on e.dept_id=dept.id;

多表查询案例

MySQL数据库查询之多表查询总结

数据准备:

create table salgrade (
    grade int,
    losal int comment '本薪资等级的最低界限',
    hisal int comment '最高界限'
) comment '薪资等级表';
insert into salgrade values (1,0,3000);
insert into salgrade values (2,3001,5000);
insert into salgrade values (3,5001,8000);
insert into salgrade values (4,8001,10000);
insert into salgrade values (5,10001,15000);
insert into salgrade values (6,15001,20000);
insert into salgrade values (7,20001,25000);
insert into salgrade values (8,025001,30000);

1.查询员工的姓名,年龄,职位,部门信息(隐式内连接)

select e.name, e.age, e.job, d.* 
from emp e, dept d 
where e.dept_id=d.id;

2.查询年龄小于30的员工的姓名、年龄、职位、部门信息(显示内连接)

select e.name,e.age,e.job,d.*
from emp e
inner join dept d on e.dept_id = d.id
where e.age<30;

3.查询拥有员工的部门id,部门名称

select distinct d.id,d.name
from emp e, dept d
where d.id=e.dept_id;

4.查询所有年龄大于40的员工,及其归属部门名称,如果员工没有分配部门也要显示

select e.*,d.name
from emp e
left outer join dept d on e.dept_id = d.id
where e.age>40;

5.查询所有员工的工资等级

select e.*,s.grade
from emp e, salgrade s
where e.salary between s.losal and s.hisal;

6.查询研发部所有员工的信息即工资等级

select e.*,s.grade
from emp e,dept d,salgrade s
where (e.dept_id=d.id) and (d.name='研发部') and (e.salary between s.losal and s.hisal);

7.查询研发部员工的平均工资

select avg(e.salary)
from emp e, dept d
where e.dept_id=d.id and d.name='研发部';

8.查询工资比灭绝高的员工信息

select *
from emp
where emp.salary > (
                      select e.salary
                      from emp e
                      where e.name='灭绝'
                      );

9.查询比平均薪资高的员工信息

select *
from emp
where salary> (
    select avg(e.salary)
    from emp e
    );

10.查询低于本部门平均工资的员工信息

select *
from emp
where emp.salary<(
    select avg(salary)
    from emp e
    where e.dept_id=emp.dept_id
    );

11.查询所有部门信息,并统计部门的员工人数

select d.*, (
    select count(*)
    from emp
    where emp.dept_id=d.id
    )
from dept d;

MySQL数据库查询之多表查询总结

总结

到此这篇关于MySQL数据库查询之多表查询的文章就介绍到这了,更多相关MySQL多表查询内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
详解MySQL 联合查询优化机制
May 10 MySQL
MySQL 分页查询的优化技巧
May 12 MySQL
mysql 8.0.24版本安装配置方法图文教程
May 12 MySQL
MySQL不使用order by实现排名的三种思路总结
Jun 02 MySQL
详解MySQL中的pid与socket
Jun 15 MySQL
Centos7中MySQL数据库使用mysqldump进行每日自动备份的编写
Aug 02 MySQL
Arthas排查Kubernetes中应用频繁挂掉重启异常
Feb 28 MySQL
mysql数据插入覆盖和时间戳的问题及解决
Mar 25 MySQL
MySQL插入数据与查询数据
Mar 25 MySQL
MYSQL中文乱码问题的解决方案
Jun 14 MySQL
mysql sock文件存储了什么信息
Jul 15 MySQL
MySQL使用IF语句及用case语句对条件并结果进行判断 
Sep 23 MySQL
分享很少见很有用的SQL功能CORRESPONDING
Aug 05 #MySQL
MySQL存储过程及语法详解
Aug 05 #MySQL
MySQL自定义函数及触发器
Aug 05 #MySQL
MySQL性能指标TPS+QPS+IOPS压测
Aug 05 #MySQL
Mysql中mvcc各场景理解应用
Aug 05 #MySQL
数据设计之权限的实现
一文解答什么是MySQL的回表
Aug 05 #MySQL
You might like
PHP禁止页面缓存的代码
2011/10/23 PHP
微博短链接算法php版本实现代码
2012/09/15 PHP
PHP实现C#山寨ArrayList的方法
2015/07/16 PHP
PHP框架laravel的.env文件配置教程
2017/06/07 PHP
Yii2 中实现单点登录的方法
2018/03/09 PHP
jQuery autocomplete插件修改
2009/04/17 Javascript
比较简单的异步加载JS文件的代码
2009/07/18 Javascript
Extjs学习笔记之九 数据模型(上)
2010/01/11 Javascript
jquery与google map api结合使用 控件,监听器
2010/03/04 Javascript
jQuery EasyUI 布局之动态添加tabs标签页
2015/11/18 Javascript
使用Function.apply()的参数数组化来提高 JavaScript程序性能的技巧
2015/12/23 Javascript
理解javascript中的MVC模式
2016/01/28 Javascript
jQuery 如何给Carousel插件添加新的功能
2016/04/18 Javascript
jQuery简单实现title提示效果示例
2016/08/01 Javascript
JavaScript实现的鼠标响应颜色渐变效果完整实例
2017/02/18 Javascript
VUE前端cookie简单操作
2017/10/17 Javascript
vuejs实现本地数据的筛选分页功能思路详解
2017/11/15 Javascript
react中使用swiper的具体方法
2018/05/15 Javascript
Vue Cli 3项目使用融云IM实现聊天功能的方法
2019/04/19 Javascript
Vue在H5 项目中使用融云进行实时个人单聊通讯
2020/12/14 Vue.js
深入浅析Python字符编码
2015/11/12 Python
python实现按行切分文本文件的方法
2016/04/18 Python
利用python画出折线图
2018/07/26 Python
Django如何自定义model创建数据库索引的顺序
2019/06/20 Python
PyQt5笔记之弹出窗口大全
2019/06/20 Python
python实现一个点绕另一个点旋转后的坐标
2019/12/04 Python
Python模块相关知识点小结
2020/03/09 Python
python爬虫开发之selenium模块详细使用方法与实例全解
2020/03/09 Python
Idea安装python显示无SDK问题解决方案
2020/08/12 Python
Python使用Selenium模拟浏览器自动操作功能
2020/09/08 Python
基于PyTorch中view的用法说明
2021/03/03 Python
草莓网美国官网:Strawberrynet USA
2016/12/11 全球购物
Yahoo-PHP面试题3
2012/01/14 面试题
公司员工的自我评价范例
2013/11/01 职场文书
2015年保洁工作总结范文
2015/04/28 职场文书
宿舍管理制度范本
2015/08/07 职场文书