MySQL-多表查询

在这里我们讲解一下三个范式的原理和作用:

当谈论关系型数据库设计时,"范式"指的是数据库表的结构设计规范。下面是对三个主要范式的通俗易懂的解释:

第一范式(1NF):确保每个列都是原子的 第一范式要求数据库表中的每个列(字段)都只包含最基本的数据,而不包含多个值。如果一个列中包含了多个值,就需要将其分解成多个独立的列。换句话说,第一范式确保每个列都是原子的。

例如,如果有一个包含“姓名”和“电话号码”两个列的表,如果存在一个人有多个电话号码,将其拆分成多个行,每个行只包含一个电话号码。

第二范式(2NF):确保非键属性完全依赖于全部键 第二范式要求数据库表中的每个非键属性都完全依赖于表的全部键,而不是只依赖于部分键。如果某个非键属性只依赖于部分键,那么应该将其分解到一个新的表中。

例如,如果有一个包含“订单号”(键)、“产品号”(键)和“产品名称”的表,如果存在一个产品名称只与订单号有关,那么应该将“产品名称”独立成一个表,并通过订单号来关联。

第三范式(3NF):确保非键属性不相互依赖 第三范式要求数据库表中的每个非键属性都不相互依赖。换句话说,不允许一个非键属性依赖于另一个非键属性。如果出现这种情况,应该将其提取到一个独立的表中。

例如,如果有一个包含“学号”(键)、“课程号”(键)和“学生姓名”的表,如果存在一个课程号只与学生姓名有关,那么应该将“学生姓名”独立成一个表,并通过学号来关联。

这些范式的作用是确保数据库表的结构合理、无冗余、易于维护和扩展。通过遵循范式,可以尽可能地减少数据冗余,提高数据的一致性和完整性,同时也能使数据库的设计更加规范和易于理解。然而,需要根据具体的业务需求和性能考虑,灵活应用范式规范。

多表查询

目录

多表查询

多表查询必要条件:主外键相等

多表连接方式

内连接

表中无主外键,键在心中


image-20231202212348620

多表查询必要条件:主外键相等

在我们这里就是

SELECT * FROM student,grade WHERE student.studentid = grade.studentid; 通过主外键进行条件过滤,得到有意义的行

多表查询中,我们不要做无意义的操作,不要去把没用的东西也找出来

例如:下面按升级的顺序让我们来理解一下

  • 首先,把两张表拼在一起(但这是笛卡尔积的形式形成新的结果)

  • 其次,SELECT * FROM student,grade; 这就相当于把两张表用笛卡尔积的形式结合在了一起

  • 然后,SELECT student.studentid,sname,courseid,score,grade.createtime FROM student,grade WHERE student.studentid=grade.studentid; 通过主外键相等进行条件过滤,筛掉无用的笛卡尔积结果,我们只需要正确匹配的结果

image-20231202213657223

  • 同时,我们不需要所有的信息都显示出来,这也是没有意义的,反而会影响我们观察数据,所以我们直接从结果中选出自己想要的列 值的注意的是我们需要区分两张表中相同的列,否则会报错 SELECT student.studentid,sname,courseid,score,grade.createtime FROM student,grade WHERE student.studentid = grade.studentid [AND student.studentid = 'WN005'] [AND score < 60 ORDER BY score DESC]; [] 中的内容可选,自己看情况写

image-20231202214126134

这张图是对应 AND student.studentid = 'WN005' 这个条件的

image-20231202214017144

这张图是对应 AND score < 60 ORDER BY score DESC 这个条件的

  • 我们也可以选出平均值之类的数据 SELECT courseid,AVG(score) from student,grade WHERE student.studentid = grade.studentid GROUP BY courseid; 记住,我们只需要把 SELECT courseid,AVG(score) from student,grade WHERE student.studentid = grade.studentid这一部分内容的结果看做一张临时表就好,然后后面的语句的就是对单表的操作了

image-20231202214637059

  • 对表进行重命名(非必要,仅建议),以便于简化SQL语句。同时,在选择列时,也建议明确指定表名。 SELECT s.studentid,s.name,g.courseid,g.score,g.createtime FROM student s,grade g WHERE s.studentid = g.studentid;FROM student s,grade g 在FROM的时候对表名重新命名

多表连接方式

  • FROM AA,BB,CC

  • JOIN ... ON

SELECT * FROM student JOIN grade ON student.studentid = grade.studentid WHERE courseid='C01';

注意:这里只有 student.studentid = grade.studentid 这个连接条件放在 ON 后面,其他的查询条件都还放在WHERE 后面

内连接

以上的连接方式统称为 内连接

  • 如果是三张表该怎么做?

    • 比如查找成绩最差的学生的班主任是谁

      • 第一步:先从成绩表中找到成绩最差的这个人的学号(也可用姓名) SELECT studentid FROM grade WHERE ORDER BY score LIMIT 1;

        • image-20231202221331818

      • 第二步:用这个人的学号也可用姓名)去学生表中找到对应的班级编号 SELECT classid FROM student WHERE studentid = (SELECT studentid FROM grade WHERE ORDER BY score LIMIT 1);

        • image-20231202221421884

      • 第三步:通过对应的班级编号找到对应班级的班主任 SELECT teacher FROM class WHERE classid = (SELECT classid FROM student WHERE studentid = (SELECT studentid FROM grade WHERE ORDER BY score LIMIT 1));

        • image-20231202221520389

上面的方法固然可以解决问题,但未免太过嵌套导致不易分析,我们建议使用多表查询的方法

SELECT s.name,c.teacher,g.score FROM student s,grade g,class c WHERE s.studentid = g.studentid AND s.classid = c.classid ORDER BY score LIMIT 1;

让我们来分析一下这段查询语句

  • 三表查询,通过主外键相连的关系解决这个问题,student表中的studentid作为grade的外键,外键实际上为grade.studentid , student中的classid作为 classid表中的外键,外键实际上为为class.classid

  • 因此,我们需要让两对主外键相等,即 s.studentid = g.studentid AND s.classid = c.classid

  • 然后通过升序查询成绩表中的最小score来确定student表中的name(或studentid)从而达到锁定班级和班主任的目的

我需要找到s.name,c.teacher,g.score这三项,从student s,grade g,class c这三张表中去找

又因为student表中的studentid和grade表中的studentid分别作为主外键关联,student表中的classid和class表中的classid分别作为主外键相关联,于是需要s.studentid = g.studentid AND s.classid = c.classid这个条件

与此同时,我们需要对查询到的成绩score进行升序排列并找到最上面的值(也就是最小的)

此时就匹配到了我们想要的结果s.name,c.teacher,g.score这三项

表中无主外键,键在心中

在进行多表连接查询时,必须指定连接条件(通常是主外键关系),但是主外键关系没有明确在表中建立,也可以使用(毕竟只是查询,并没有做出什么增删改)

不过这样确实容易产生脏数据

无论哪个数据库,要维持主外键约束,是有性能开销的。因为要删除和修改时,要扫描一遍外表,看看能不能删除和修改

因此,有些情况下就会选择不在数据库层面建立主外约束,而在程序设计中设置主外键约束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值