硅基计划5.0 MySQL 叁 E-R关系图&联合/多表查询&三大连接&子查询&合并查询


文章目录

    • 一、E-R关系图
      • [1. 实体之间的关系](#1. 实体之间的关系)
      • [2. 简单的E-R图绘制](#2. 简单的E-R图绘制)
      • [3. 工作流程](#3. 工作流程)
      • [4. 外键约束&E-R图完成数据库/表创建](#4. 外键约束&E-R图完成数据库/表创建)
        • [1. 一对一关系](#1. 一对一关系)
        • [2. 一对多关系](#2. 一对多关系)
        • [3. 多对多关系](#3. 多对多关系)
    • 二、联合/多表查询
      • [1. 笛卡尔积](#1. 笛卡尔积)
      • 2.内连接
      • [3. 外连接](#3. 外连接)
      • [4. 自连接](#4. 自连接)
      • [5. 子查询](#5. 子查询)
      • [6. 合并查询](#6. 合并查询)

一、E-R关系图

1. 实体之间的关系

一个实体类对应的是数据库的一张表,实体之间的关系说白了就是表和表之间的关系

一共有四种关系一对一,一对多,多对多,无关系

  1. 一对一:一名学生只能有一个学生账号,并且一个学生账号只能属于一名学生
  2. 一对多:一名学生属于一个班级,但是一个班级可以包含多名学生
  3. 多对多:一名学生可以选择对多门课程,同时一门课程也可以被多名学生选择

2. 简单的E-R图绘制

这里我把刚刚的例子具体展现出来

请注意,我们以后在工作中很少直接去绘制E-R图,因为这样非常耗费时间

3. 工作流程

对需求可行性分析-->总体设计(E-R)图-->具体数据库数据表设计-->编写代码

4. 外键约束&E-R图完成数据库/表创建

我们针对不同的关系,讲讲如何设计

1. 一对一关系

就跟我们之前讲的一样,我们引入外键约束,而且我们要遵循三大范式,即一个表只能有一个主键

我们只需要在一张表中有一个列,和另外一个表建立联系就好

2. 一对多关系

我们针对这种关系,我们在"多"的那一方进行对"一"的联系

我们回到刚刚之前那个学生和班级表

对于学生和班级来说,班级是"一",学生是"多"

我们就按照上述图片在学生表中加入一列和班级表关联就好

3. 多对多关系

这个非常特殊,我们可以建立一个中间表,来构成一个桥梁

就拿我们之前的那个学生和课程之间的关系来说

我们有个学生表

sql 复制代码
create table student (
    student_id int primary key,
    name varchar(50) not null,
    major varchar(50)
);

我们有个课程表

sql 复制代码
create table course (
    course_id int primary key,
    course_name varchar(100) not null,
    credits int
);

我们写个中间关系表,构建关系

对于学号和课程好之间构成复合主键,再分别与学生表和课程表构建外键联系

sql 复制代码
create table student_course (
    student_id int,
    course_id int,
    enrollment_date date,
    grade decimal(4,2),
    primary key (student_id, course_id),  -- 复合主键,关键
    foreign key (student_id) references student(student_id),
    foreign key (course_id) references course(course_id)
);

关于E-R关系图,MySQL的workbench可以自动生成,可以自己去查阅下

这里给出一个题目和一个例子:

题目:学校食堂管理系统,包含食堂表,食堂仓口表,仓口收费记录表

sql 复制代码
create table type(house_id int primary key auto_increment,name varchar(10));

create table access(access_id int primary key auto_increment,name varchar(10),house_id int,foreign key (house_id) references type(house_id));

create table money(sign_id int primary key auto_increment,access_id int,house_id int,time datetime,foreign key (access_id) references access(access_id),foreign key (house_id) references type(house_id));

我们利用第二张表和第一张表之间的外键关系,以及第三张表和第二与第一张表的外键关系

来共同构成多个一对多关系的设计

二、联合/多表查询

我们前提是要保证查询的多个表之间要有关系,如果没有关系,那笛卡尔积没有意义

1. 笛卡尔积

我们首先来说说什么事笛卡尔积,说白了就是把所有可能的结果都枚举出来

举个例子

好,通过观察这个表,我们发现有两条是不合理数据,即张三怎么是二班的还有李四怎么是一班的

这就是笛卡尔积的计算结果,我们要自己手动取出不合理结果,即我们要保证两个班级id要统一

这个class_id就是连接两张表之间的桥梁,我们就称为连接条件

好,我们来演示去重

sql 复制代码
create table class1(class_id int primary key auto_increment,class_name varchar(3));

insert into class1 values(1,'一班'),(2,'二班');

create table student1(student_id int,name varchar(10),class_id int,foreign key student1(class_id) references class1(class_id));

insert into student1 values(1001,'张三',1),(1002,'李四',2);

select * from class1,student1;

select * from class1,student1 where class1.class_id = student1.class_id;

之后的操作和单表查询一样,都可以利用之前学的查询语句去增删改查等等

2.内连接

这个内连接说白了就是我们之前笛卡尔积的同义替换,可以相互转化

语法 ... (inner) join ... on (条件)

像我们之前的笛卡尔积计算,我们可以这么写

比如我们联合查询学生表和班级表

sql 复制代码
select * from student inner join class;

引入连接条件去重

sql 复制代码
select * from student inner join class on student.class_id = class.class_id;

再针对列进行筛选

sql 复制代码
select * from student inner join class on student.class_id = class.class_id where student.name = '张三';

我们可以看到当使用join on语句后,并不影响我们where语句的使用

那既然两者都一样,那我们为什么还要使用jion on呢?

这是因为我们在join on语句中能够拥有很多条件,更加利于我们查询

如果想让多个表连接,比如以下多对多关系的表,我们可以搭配多组join on语句

sql 复制代码
select * from join score on student.student_id = score.student_id join course on score.course_id = course.course_id;

3. 外连接

这个不能通过where语句写,只能通过join on方式写,以下我举个例子来演示下

这个外连接分位左外连接和右外连接

首先我们拿一对一关系的表来演示下

sql 复制代码
use home;

show tables;

create table student2(id int,name varchar(20));

create table score(student_id int,score int);

insert into student2 values(1,'张三'),(2,'李四'),(3,'王五');

insert into score values(1,90),(2,80),(3,70);

当我们使用内连接和外连接的时候,结果是一样的

但是如果不是一对一的关系,就会存在差别

比如我们把成绩表中70分的成绩的学号修改为4

sql 复制代码
update score set student_id = 4 where score = 70;

好,现在我们再来看左外连接和右外连接的结果

外连接本质上就是笛卡尔积

左外连接,因为学号为三的王五在成绩表中不存在,因此三班王五并没有直接参与笛卡尔积运算,而是把另一张表中不存在的数据标记为空

同理右外连接,因为学号四在学生表中不存在,因此学号四号也并没有直接参与笛卡尔积,同理而是把另一张表中不存在的数据标记为空

但是总得来说,我们平时还是要避免这种几张表中数据不对等的情况

4. 自连接

我们之前都是列与列之间的比较,比如语文成绩大于数学成绩

但是如果是这样的,每一行表示一门成绩

我们之前由于都是一行代表一个学生所有成绩

但是现在成绩是一条一条插入的,这样我们如何比较呢,比如我们想查看MySQL成绩大于数据结构成绩的学生信息

因此现在我们就要进行内连接查询,但是如果你直接写内连接,会报错

提示列名重复,怎么办呢,诶!我们可以起别名啊,这样不就行了,同时再把去重条件加上

观察这张表,我们要比较MySQL成绩大于数据结构成绩,那我们不是直接可以比较条件就是
s1.class_id = 1 and s2.class_id = 2 and s1.score > s2.score

因此我们加上限制语句写

但是如果我们并不知道课程号的对应关系,我们还可以联合其他表进行多表查询

但是,在实际开发环境中,我们并不建议使用诸如笛卡尔积这种查询方法,如果表的数据非常庞大,这样的笛卡尔积算起来费时费力

因此在以后的开发环境中,我们使用诸如Java等其他语言对MySQL进行查询操作

5. 子查询

这个子查询其实是和我们的SQL常识相反的存在

子查询说白了就是把一个SQL的查询结果当成另一个SQL的一部分,它可以是另一个SQL语句的条件。同时,因为查询的结果是一个表,因此它还可以和其他表进行笛卡尔积

我们就拿以下数据来举例子

我们想查询和张三同班的同学信息

如果按照一般方式,我们要分两步走

第一步是先查询张三位于哪个班级,第二步再是筛选出这个班级的其他同学同时不包含张三本人

sql 复制代码
select class_id from student3 where name = '张三';

select * from student3 where class_id = 1;

如果我们使用子查询,就是这样

sql 复制代码
select * from student3 where class_id = (select class_id from student3 where name = '张三') and name != '张三';

如果是多个行,也是一样的写法,比如查找成绩表中张三和李四的成绩

sql 复制代码
select * from course3 where student_id in (select id from student3 where name = '张三' or name = '李四');

对于多个列的子查询,或者在from子句中的查询,这里就不再赘述,就是和我们之前讲的单表或者是多表查询是一样的

6. 合并查询

这个和刚刚的子查询类似,但是这种查询写法客服行更高

合并查询就是把多个SWL 查询的结果合并为一个集合,关键字unionunion all

我们再创建一个新的表

如果我想查询student3表中一班的同学和新的这张表中三班的同学

sql 复制代码
select * from student3 where class_id = 1 union select * from student4 where class_id = 3;# 使用union代表结果去重,union all代表结果不去重

这里说个注意事项,在进行合并查询的时候,要保证查询的多个表之间的列个数,列的类型要匹配,对于列名并无特殊要求


希望本篇文章对您有帮助,有错误您可以指出,我们友好交流


END

相关推荐
Gold Steps.2 小时前
MySQL 8+ 日志管理与数据备份恢复实战指南
数据库·mysql·数据安全
程序员鱼皮2 小时前
老弟第一次学 Redis,被坑惨了!小白可懂的保姆级 Redis 教程
数据库·redis·程序员
kyle~2 小时前
C++---嵌套类型(Nested Types)封装与泛型的基石
开发语言·c++·算法
sali-tec2 小时前
C# 基于halcon的视觉工作流-章48-短路断路
开发语言·图像处理·人工智能·算法·计算机视觉
学工科的皮皮志^_^3 小时前
网口学习理解
经验分享·笔记·嵌入式硬件·学习·fpga开发·以太网
oak隔壁找我3 小时前
Druid 数据库连接池源码详细解析
java·数据库·后端
不剪发的Tony老师3 小时前
Yearning:一个免费开源的SQL审核平台
数据库·sql·mysql
无敌最俊朗@3 小时前
解决 QML 中使用 Qt Charts 崩溃的三个关键步骤
开发语言·qt