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多表查询-笔记七
Apr 05 MySQL
mysql 8.0.24版本安装配置方法图文教程
May 12 MySQL
MySQL中出现乱码问题的终极解决宝典
May 26 MySQL
SQL IDENTITY_INSERT作用案例详解
Aug 23 MySQL
mysql函数全面总结
Nov 11 MySQL
JMeter对MySQL数据库进行压力测试的实现步骤
Jan 22 MySQL
CentOS 7安装mysql5.7使用XtraBackUp备份工具命令详解
Apr 12 MySQL
深入理解MySQL中MVCC与BufferPool缓存机制
May 25 MySQL
MySQL数据库安装方法与图形化管理工具介绍
May 30 MySQL
MySQL慢查询中的commit慢和binlog中慢事务的区别
Jun 16 MySQL
MySQL transaction事务安全示例讲解
Jun 21 MySQL
MySQL一劳永逸永久支持输入中文的方法实例
Aug 05 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 之 写时复制介绍(Copy On Write)
2014/05/13 PHP
JavaScript 在各个浏览器中执行的耐性
2009/04/06 Javascript
两种WEB下的模态对话框 (asp.net或js的分别实现)
2009/12/02 Javascript
IE8下关于querySelectorAll()的问题
2010/05/13 Javascript
利用Keydown事件阻止用户输入实现代码
2014/03/11 Javascript
JS的事件绑定深入认识
2014/06/26 Javascript
jQuery通过点击行来删除HTML表格行的实现示例
2014/09/10 Javascript
jquery滚动特效集锦
2015/06/03 Javascript
jquery输入数字随机抽奖特效的简单实现代码
2016/06/10 Javascript
全面解析Javascript无限添加QQ好友原理
2016/06/15 Javascript
JS控制HTML元素的显示和隐藏的两种方法
2016/09/27 Javascript
Bootstrap基本组件学习笔记之进度条(15)
2016/12/08 Javascript
JS实现给json数组动态赋值的方法示例
2020/03/19 Javascript
vue音乐播放器插件vue-aplayer的配置及其使用实例详解
2017/07/10 Javascript
vue实现图书管理demo详解
2017/10/17 Javascript
详解React中合并单元格的正确写法
2019/01/08 Javascript
vscode下vue项目中eslint的使用方法
2019/01/13 Javascript
Vue 自定义指令实现一键 Copy功能
2019/09/16 Javascript
javascript操作元素的常见方法小结
2019/11/13 Javascript
基于JS正则表达式实现模板数据动态渲染(实现思路详解)
2020/03/07 Javascript
Vue 的 v-model用法实例
2020/11/23 Vue.js
用Python进行一些简单的自然语言处理的教程
2015/03/31 Python
在Python中操作文件之truncate()方法的使用教程
2015/05/25 Python
Python统计文件中去重后uuid个数的方法
2015/07/30 Python
Python函数中*args和**kwargs来传递变长参数的用法
2016/01/26 Python
使用python3.5仿微软记事本notepad
2016/06/15 Python
Python制作一个仿QQ办公版的图形登录界面
2020/09/22 Python
详解通过HTML5 Canvas实现图片的平移及旋转变化的方法
2016/03/22 HTML / CSS
h5实现获取用户地理定位的实例代码
2017/07/17 HTML / CSS
喜诗官方在线巧克力店:See’s Candies
2017/01/01 全球购物
2014年寒假社会实践活动心得体会
2014/04/07 职场文书
国际贸易系求职信
2014/08/09 职场文书
信访工作汇报材料
2014/10/27 职场文书
保管员岗位职责
2015/02/14 职场文书
javascript Number 与 Math对象的介绍
2021/11/17 Javascript
MySQL 字符集 character
2022/05/04 MySQL