目录

多表关系

一对多

多对多

一对一

多表查询概述

数据准备

概述

分类

内连接

外连接

自连接

联合查询

子查询

列子查询

行子查询

表子查询

多表查询


多表关系

  • 一对一
  • 一对多(多对一)
  • 多对多

一对多

  • 案例:部门与员工
  • 关系:一个部门对应多个员工,一个员工对应一个部门
  • 实现:在多的一方建立外键,指向一的一方的主键

多对多

案例:学生与课程(老师)的关系

关系:一个学生可以选修多门课程,一个课程可以有多个学生选择

实现:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键

一对一

  • 案例: 用户与用户详情的关系。
  • 关系: 一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另 一张表中,以提升操作效率。
  • 实现: 在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)。

多表查询概述

数据准备

1). 删除之前 emp, dept表的测试数据

2). 执行如下脚本,创建emp表与dept表并插入测试数据


# 创建emp表,并插入数据
DROP TABLE IF EXISTS emp;
CREATE TABLE emp(
id INT AUTO_INCREMENT COMMENT 'ID' PRIMARY KEY,
NAME VARCHAR(50) NOT NULL COMMENT '姓名',
age INT COMMENT '年龄',
job VARCHAR(20) COMMENT '职位',
salary INT COMMENT '薪资',
entrydate DATE COMMENT '入职时间',
managerid INT COMMENT '直属领导ID',
dept_id INT COMMENT '部门ID'
)COMMENT '员工表';# -- 添加外键
ALTER TABLE emp ADD CONSTRAINT fk_emp_dept_id FOREIGN KEY (dept_id) REFERENCES
dept(id);INSERT INTO emp (id, NAME, age, job,salary, entrydate, managerid, dept_id)
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);

dept表结构

 emp表结构

概述

多表查询就是从多个表中查询数据

那么我们要执行多表查询,就只需要使用逗号分隔多张表即可,

如: select * from emp ,dept ; 具体的执行结果如下:

此时,我们看到查询结果中包含了大量的结果集,总共102条记录,而这其实就是员工表emp所有的记录 (17) 与 部门表dept所有记录(6) 的所有组合情况,这种现象称之为笛卡尔积。接下来,就来简单 介绍下笛卡尔积。

我们通常在查询数据时候需要消除笛卡尔积

由于id为17的员工,没有dept_id字段值,所以在多表查询时,根据连接查询的条件并没有查询 到。

分类

  • 连接查询

    • 内连接:相当于查询A,B交集部分
    • 外连接
      • 左外连接,查询左表所有数据以及两张表交集部分数据
      • 右外连接,查询右表所有数据以及两张表交集部分数据
    • 自连接:当前表与自身的连接查询,自连接必须使用表别名
    • 子查询

内连接

1). 隐式内连接

select 字段 from 表1,表2 where 连接条件;

2). 显示内连接

select 字段 from 表1 join 表2 on 连接条件;

案例:

查询每个员工的姓名,及管理的部门名称

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

查询每一个员工的姓名 , 及关联的部门的名称 (显式内连接实现)

select e.name, d.name from emp as e join dept as d on e.dept_id = d.id;

注意:一旦为表起了别名,就不能再使用表名来指定对应的字段了,此时只能够使用别名来指定字 段。

外连接

外连接分为 左外连接 和 右外连接。 具体语法如下:

1). 左外连接

select 字段 from 表1 left join 表2 on 条件;

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

2).右外连接

SELECT 字段列表 FROM 表1 RIGHT [ OUTER ] JOIN 表2 ON 条件 ... ;

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

select 字段 from 表1 left join 表2 on 条件;# 等价于select 字段 from 表2 right join 表1 on 条件;

案例:

查询emp表中所有数据和对象部门信息。

SELECT e.*,d.name FROM emp e LEFT JOIN dept d ON e.`dept_id` = d.`id`;

查询dept表中的所有数据和对应的员工信息(右外连接)

select d.*, e.* from emp e right outer join dept d on e.dept_id = d.id;

自连接

自连接查询,顾名思义,就是自己连接自己,也就是把一张表连接查询多次。我们先来学习一下自连接 的查询语法:

SELECT 字段列表 FROM 表A 别名A JOIN 表A 别名B ON 条件;

查询员工及其领导的名字

SELECT e.name AS '员工名', d.name AS '领导名' FROM emp e, emp d WHERE e.`managerid` = d.`id`;

注意事项:

在自连接查询中,必须要为表起别名,要不然我们不清楚所指定的条件、返回的字段,到底 是哪一张表的字段。

联合查询

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

SELECT 字段列表 FROM 表A ...
UNION [ ALL ]
SELECT 字段列表 FROM 表B ....;
  • 对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致。
  • union all 会将全部的数据直接合并在一起,union 会对合并之后的数据去重。

案例:

将薪资低于5000员工和年龄大于50员工都查询出来

当前对于这个需求,我们可以直接使用多条件查询,使用逻辑运算符 or 连接即可。 那这里呢,我们 也可以通过union/union all来联合查询.

select * from emp where salary <5000
union
select * from emp where age >50 ;

注意:union 和 union all的区别,这里直接使用了union 进行去重。

子查询

SQL语句中嵌套SELECT语句,称为嵌套查询,又称子查询。

SELECT * FROM t1 WHERE column1 = ( SELECT column1 FROM t2 )

子查询外部的语句可以是INSERT / UPDATE / DELETE / SELECT 的任何一个。

根据子查询结果不同分为:

  • 标量子查询(子查询结果为单个值)
  • 列子查询(子查询结果为一列)
  • 行子查询(子查询结果为一行)
  • 表子查询(子查询结果为多行多列)

根据子查询位置,分为:

  • WHERE之后
  • FROM之后
  • SELECT之后

标量子查询

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

A. 查询 "销售部" 的所有员工信息

1、 先查询销售部---作为前提条件

select id from dept where name = '销售部';

2、后查询所有员工信息

select * from emp where dept_id  = (select id from dept where name = '销售部');

B. 查询在 "方东白" 入职之后的员工信息

1. 查询东方白的入职时间

select entrydate from emp where name = '方东白';

2. 查询入职时间大于东方白的员工信息

select * from emp where entrydate > (select entrydate from emp where name = '方东白');

列子查询

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

常用的操作符:IN 、NOT IN 、 ANY 、SOME 、 ALL

案例:

A. 查询 "销售部" 和 "市场部" 的所有员工信息

1. 查询市场部和销售部的id(查出来是多个数据)

select id from dept where name = '销售部' or name = '市场部';

2. 根据id查信息

select * from emp where dept_id in (select id from dept where name = '销售部' or name = '市场部');

B. 查询比 财务部 所有人工资都高的员工信息

1. 查询财务部人中所有人的工资

select salary from emp where dept_id = (select id from dept where name = '财务部');

2. 使用all 命令

SELECT * FROM emp WHERE salary > ALL(SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE NAME = '财务部'));

C. 查询比研发部其中任意一人工资高的员工信息

1. 查询研发人员的信息

select salary from emp where dept_id = (select id from dept where name = '研发部');

2. 使用any

select * from emp where salary > any(select salary from emp where dept_id = (select id from dept where name = '研发部'));

行子查询

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

常用的操作符:= 、<> 、IN 、NOT IN

案例:

A. 查询与 "张无忌" 的薪资及直属领导相同的员工信息;

1. 查询账务的薪资及其直属领导

select salary, managerid from emp where name = '张无忌';

2. 查询员工信息

select * from emp where (salary,managerid) = (select salary, managerid from emp where name = '张无忌');

表子查询

子查询返回的结果是多行多列,这种子查询称为表子查询。

常用的操作符:IN

案例:

A. 查询与 "鹿杖客" , "宋远桥" 的职位和薪资相同的员工信息

分解为两步执行:

1. 查询 "鹿杖客" , "宋远桥" 的职位和薪资

select job, salary from emp where name = '鹿杖客' or name =  '宋远桥';

2. 查询与 "鹿杖客" , "宋远桥" 的职位和薪资相同的员工信息

SELECT * FROM emp WHERE (job,salary) IN (SELECT job, salary FROM emp WHERE NAME = '鹿杖客' OR NAME = '宋远桥');

多表查询

数据环境准备:

##
drop table if exists salgrade;
create table salgrade(
grade int,
losal int,
hisal int
) 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,25001,30000);

在这个案例中,我们主要运用上面所讲解的多表查询的语法,完成以下的12个需求即可,而这里主要涉 及到的表就三张:emp员工表、dept部门表、salgrade薪资等级表 。

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

  • 表: emp , dept
  • 连接条件: emp.dept_id = dept.id
SELECT e.name, e.age, e.job, d.name FROM emp e, dept d WHERE e.dept_id = d.id;

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

  • 表: emp , dept
  • 连接条件: emp.dept_id = dept.id
select  e.name , e.age , e.job , d.name  from emp e join dept d on e.dept_id = d.id where age < 30;

3). 查询拥有员工的部门ID、部门名称

  • 表: emp , dept
  • 连接条件: emp.dept_id = dept.id
  • 查询结果有重复,需要进行去重
SELECT DISTINCT d.id, d.name FROM emp e, dept d WHERE e.dept_id = d.id;

4). 查询所有年龄大于40岁的员工, 及其归属的部门名称; 如果员工没有分配部门, 也需要展示出来(外连接)

  • 表: emp , dept
  • 连接条件: emp.dept_id = dept.id
SELECT e.*,d.`name` FROM emp e LEFT JOIN dept d ON e.`dept_id` = d.`id` WHERE e.`age`>40;

备注: 以上需求的实现方式可能会很多, SQL写法也有很多,只要能满足我们的需求,查询出符合条 件的记录即可。

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

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

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

SELECT e.* ,d.`name`, s.grade FROM emp e , dept d , salgrade s WHERE e.dept_id = d.id AND (
e.salary BETWEEN s.losal AND s.hisal ) AND d.name = '研发部';

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

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

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

①. 查询 "灭绝" 的薪资

select salary from emp where name = '灭绝';

②. 查询比她工资高的员工数

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

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

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

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

①. 查询指定部门平均薪资

select avg(e1.salary) from emp e1 where e1.dept_id = 1;

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

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

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

select d.id, d.name , ( select count(*) from emp e where e.dept_id = d.id ) '人数'
from dept d;

数据库学习记录9一文详解多表查询相关推荐

  1. mysql单表查询实例_MySQL简单查询详解-单表查询

    MySQL简单查询详解-单表查询 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查询的执行路径 一条SQL查询语句的执行过程大致如下图所示: 1>.客户端和服务端通过my ...

  2. 第七章、模型详解 -- 多表查询

    通过对象进行多表查询 由一到多查询:一类模型类对象名.小写多类模型类类名_set.查询函数() 通过对象查询分成2步,先查到某本图书,再通过该图书对象查询该图书中的人物对象 实例演练: 查询id为1的 ...

  3. 【Numpy学习记录】np.cov详解

    写在篇前   在概率论和统计学中,协方差用于衡量两个变量的总体误差.而方差是协方差的一种特殊情况,即当两个变量是相同的情况.其定义的数学形式是:Cov(X,Y)=E[(X−E(X))(Y−E(Y))] ...

  4. Pandas获取SQL数据库read_sql()函数及参数一文详解+实例代码

    前言 Pandas常用作数据分析工具库以及利用其自带的DataFrame数据类型做一些灵活的数据转换.计算.运算等复杂操作,但都是建立在我们获取数据源的数据之后.因此作为读取数据源信息的接口函数必然拥 ...

  5. 「软件项目管理」一文详解软件配置管理计划

    一文详解软件配置管理计划 前言 一.配置管理概述 1. 配置管理(SCM)定义 2. 软件配置项目(SCI) 3. 基线 4. 软件配置控制委员会(SCCB) 二.软件配置管理过程 1. 管理过程 2 ...

  6. 【卷积神经网络结构专题】一文详解AlexNet(附代码实现)

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! [导读]本文是卷积神经网络结构系列专题第二篇文章,前面我们已经介绍了第一个真正意义 ...

  7. 一文详解 YOLO 2 与 YOLO 9000 目标检测系统

    一文详解 YOLO 2 与 YOLO 9000 目标检测系统 from 雷锋网 雷锋网 AI 科技评论按:YOLO 是 Joseph Redmon 和 Ali Farhadi 等人于 2015 年提出 ...

  8. 一文详解决策树算法模型

    AI有道 一个有情怀的公众号 上文我们主要介绍了Adaptive Boosting.AdaBoost演算法通过调整每笔资料的权重,得到不同的hypotheses,然后将不同的hypothesis乘以不 ...

  9. mysql二进制方式_MySQL数据库之MySql二进制连接方式详解

    本文主要向大家介绍了MySQL数据库之MySql二进制连接方式详解 ,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助. 使用mysql二进制方式连接 您可以使用MySQL二进制方式进 ...

最新文章

  1. tensorflow1
  2. 读WEB标准和网站重构后的一些感想
  3. 你所需要的java基础篇深入解析大汇总
  4. Service Mesh 是新瓶装旧酒吗?
  5. jgroups传输消息_使用JGroups进行ElasticMQ消息复制
  6. java 头像 微信群_java怎么生成带用户微信头像的图片,并把这张图片发送给用户。...
  7. 我认为测试应该掌握的SQL语句
  8. navicat mysql 还原_navicat如何给mysql还原数据库
  9. 软件开发者优质资源网站
  10. 使用Batch Normalization折叠来加速模型推理
  11. ArcEngine 相关-转载
  12. APP开通支付宝支付 转账功能
  13. cocoscreator修改图标
  14. 修改MacOSX 启动菜单中磁盘名称
  15. ascii码中的A的代码是什么?
  16. Java数据类型之Java数据类型的划分方式
  17. 3dsmax2014插件开发之环境搭建
  18. cpm自动SEO写文章 关键词文本生成工具3.0版本
  19. 笛卡儿积、自然连接、等值连接的区别
  20. 链路层典型协议(简述)

热门文章

  1. 问题 B: 首字母大写
  2. Linux系统服务管理
  3. 无线网卡服务器关闭了怎么办,win7系统thinkpad无线网卡自动关闭怎么办
  4. 同内存版本差价400!OPPO华为千元5G谁更具性价比?
  5. flex布局(弹性盒子一)
  6. Unity小狐狸学习日志、关于角色创立,移动控制以及跳跃动画等方面
  7. 单片机 rs232 c语言,完全手册 51单片机C语言开发详解系列之第8章 串口通讯实战—RS232...
  8. 游戏自动化测试-局内战斗
  9. 遇见OFFER|一汽-大众成都数字化研发中心,专场招聘来啦!
  10. 树莓派摄像头打不开的问题