MySQL:表的设计原则和聚合函数
所属专栏:MySQL学习
💎1. 表的设计原则
1. 从需求中找到类,类对应到数据库中的实体,实体在数据库中表现为一张一张的表,类中的属性对应着表中的字段
2. 确定类与类的对应关系
3. 使用SQL去创建具体的表
范式:范式描述的是数据关系的模型(一对一关系,一对多关系,多对多关系)
分类:第一范式(1NF),第二范式(2NF),第三范式(3NF),BC范式(BCNF)
💎2. 三大范式
💎2.1 第一范式
规定:表中的数据不能再分,在定义表的时候,对照数据中的数据类型,每一个字段都可以用一个数据类型标识,那么当前这个表就满足第一范式
例如:定义一个学生表,其中的字段有:学号,姓名,年龄,班级名,学校名,学校地址,这就符合了第一范式,但是如果是:学号,姓名,年龄,班级名,学校,这就不符合第一范式,因为无法找到一个数据类型来表示学校这个对象
关系型数据库的一个最基本的要求,不满足第一范式就不能称为关系型数据库
💎2.2 第二范式
在满足第一范式的基础上,不存在非关键字段(非主键字段)对任意候选键(主键,外键,没有主键时的唯一键)的部分函数依赖(存在与复合主键的情况下),就满足第二范式,复合主键在上一篇文章中已经介绍过,一个表中不能有两个主键,但是一个主键中可以包含多个列,这时的主键就是复合主键
也就是说,如果这个表不含复合主键,那么这个表就满足第二范式
先来看一个表中存在复合主键的情况下,存在非关键字段对候选键的部分函数依赖的不符合第二范式的反例:
学号 | 姓名 | 年龄 | 课程名称 | 学分 | 成绩 |
202201 | 张三 | 19 | MySQL | 3 | 100 |
其中,年龄和姓名依赖学号(对应唯一学号),学分依赖课程名称,成绩通过学生和课程共同区分,也就是这个表中可以用学生和课程作为复合主键来确定学生当前的课程成绩,对与其他的,学分和学号,学生姓名等没有关系,学生的姓名和课程名等也没有关系
像这样的,对于由两个或多个关键字段共同决定一条记录(存在复合主键)的情况,如果一行数据中有些字段只与关键字段中的一个有关系,那么就称为只存在部分函数依赖,对于这样的情况就不满足第二范式
接下来看一个正面例子:
对于这样的设计,每张表都有非主键字段,都强依赖与主键,第三个表存在的复合主键,非主键依赖于两个主键的字段,不存在部分函数依赖,满足第二范式
不符合第二范式的时候的弊端:
学号 | 姓名 | 年龄 | 课程名称 | 学分 | 成绩 |
202201 | 张三 | 19 | MySQL | 3 | 100 |
202202 | 李四 | 19 | MySQL | 3 | 100 |
202203 | 王五 | 20 | Java | 2 | 95 |
202204 | 赵六 | 19 | Java | 2 | 96 |
1. 数据冗余
学生的年龄和学分大量出现,造成数据冗余
2. 更新异常
如果需要修改MySQL的学分,那么就需要修改表中所有关于MySQL的记录,如果说只有部分数据修改成功,剩余的还是原来的数据,就会出现数据不一致,造成数据混乱
3. 插入异常
当前表格在有学生录入成绩后才能查看课程的学分信息,例如:如果说这时学校加入一门新课,但学生都没有考过试,那么这门新课在数据库就就没有记录
4. 删除异常
同插入异常一样,如果需要删除学生成绩,例如,把选Java的两位同学成绩删除,那么此时在数据库中就又没有Java这门课程的学分信息了
💎2.3 第三范式
在第二范式的基础上,不存在非关键字段对任意候选键的传递依赖
学号 | 姓名 | 年龄 | 所在学院 | 学院地址 |
在这个表中,描述的主要对象是学生,所以学号可以作为主键,此时,姓名和年龄与学号是强相关的,学院地址与所在学院是强相关的,描述学生所在学院,只需要把学生和学院建立一个关联关系即可,这两个强相关关系存在传递现象 学号->所在学院->学院地址 ,这种传递关系就称为传递依赖,所以说这种设计不满足第三范式
根据学生与学院的关系,拆分为两张表就满足了第三范式:
学院编号 | 学院名称 | 学院地址 |
学号 | 姓名 | 年龄 | 学院编号 |
这样设计,两张表都依赖与自己表中的主键,学生表可以通过外键与学院之间建立关联关系
💎3. 三种关系
💎3.1 一对一关系
例如设计一个登录界面,输入用户名和密码登录成功之后,显示欢迎用户,这样的场景一般对应两个实体,用户和账号,并且一个用户只对应一个账号,就是一对一的关系
针对一对一关系设计表时有两种方式
第一种就是把两个实体所有的信息放在一张表中
use_id | name | phone_number | username | password |
第二种就是设计两张表,分别记录用户信息和账号信息,再把两张表关联起来
1.第一种关联方式就是通过用户id进行关联,场景:当输入用户名和密码并校验成功之后,再通过用户id去查找用户的name
user_id | name | phone_number |
account_id | username | password | user_id |
2.第二种关联方式通过account_id进行关联
account_id | username | password |
user_id | name | phone_number | account_id |
💎3.2 一对多关系
一对多关系其实很常见,例如学生和班级的关系:一个班级中可以有多个学生
创建学生和班级表:
class_id | name |
student_id | name | class_id |
💎 3.3 多对多关系
例如学生进行选课,一个学生可以选多门课,一门课可以被多名学生选择
分别创建实体表:
course_id | name |
1 | MySQL |
2 | Java |
student_id | name | age |
202201 | 张三 | 19 |
202202 | 李四 | 20 |
创建关系表
id | student_id | course_id |
1 | 202201 | 1 |
2 | 202202 | 1 |
3 | 202202 | 2 |
通过关系表,就可以记录每位同学选择的课程,并且符合第二范式,修改学生的年龄字段时也不会影响到关系表
最后把之前讲到的综合起来创建一张成绩表
-- 班级表
create table class
(class_id bigint primary key auto_increment,name varchar(20) not null
);-- 学生表
create table student
(student_id bigint primary key auto_increment,name varchar(20) not null,age bigint,class_id bigint,-- 设置class_id为class表class_id的外键foreign key (class_id) references class (class_id)
);-- 课程表
create table course
(course_id bigint primary key auto_increment,name varchar(50) not null
);
-- 成绩表
create table score
(score_id bigint primary key auto_increment,student_id bigint,course_id bigint,score decimal(5, 2),-- 设置student_id为student表student_id的外键foreign key (student_id) references student (student_id),-- 设置course_id为course表course_id的外键foreign key (course_id) references course (course_id)
);
💎4. 新增
需求:创建一个新表,把原来的表的数据内容复制到新表中
我们有以下几种解决方法:
1. 一条一条的插入,很明显,这种方法很麻烦,如果数据量很大就不好操作
2. 把原来的数据导出来,再把表名修改一下,再改入到目录表中
3. 使用 insert into select 语句
第二个方法就是在 navicat 中直接进行表的复制
下面来看使用 insert into select 语句的方法
-- 新建一张表,把旧表导入到新表中
create table new_student
(id bigint primary key auto_increment,name varchar(50)
);
-- 把在原来的表中查到的数据插入到新的表中
insert into new_student
select id, name
from student;
需要注意的就是,查询到的列和要插入的列要匹配,不然就会报错
💎5. 聚合函数
函数 | 说明 |
COUNT([DISTINCT] expr) | 返回查询到的数据的数量 |
SUM([DISTINCT] expr) | 返回查询到的数据的总和 |
AVG([DISTINCT] expr) | 返回查询到的数据的平均值 |
MAX([DISTINCT] expr) | 返回查询到的数据的最大值 |
MIN([DISTINCT] expr) | 返回查询到的数据的最小值 |
💎5.1 COUNT() 统计所有行
-- 统计表中的行数
select count(*)
from student;
-- 也可以传入常量 1
select count(1)
from student;
星号(*)并不直接表示表中的任意一列,而是作为一个特殊的指示符,告诉数据库管理系统(DBMS)计算表中的行数,而不关心表中的列内容或是否有NULL值。
还可以指定某一列进行统计:
-- 指定列统计
select count(id)
from student;select count(name)
from student;
💎5.2 SUM() 求和
创建一张成绩表,计算语文的总成绩
create table exam
(id bigint primary key auto_increment,name varchar(20),chinese decimal(5, 2),math decimal(5, 2)
);
insert into exam(id, name, chinese, math)
values (1, '张三', 98, 95),(2, '李四', 97, 99),(3, '王五', 96, 98),(4, '赵六', 97, 94);
-- 计算语文总成绩
select *
from exam;
select sum(chinese)
from exam;
查询到的结果存储在了临时表中,不受字段中长度的约束(decimal(5, 2))
如果说求和的那一列存在null的话,会是像之前表达式相加时,null加上任何值都是null的情况吗?
insert into exam values (5,'钱七',96,null);select sum(math)
from exam;
可以看出,最终的值并没有加上null ,并且,如果是非数值类型求和是没有意义的
💎5.3 AVG() 求平均值
-- 求平均值
select avg(math)
from exam;-- 参数里边可以包含表达式,结果可以使用别名
select avg(math + chinese) as 总分平均值
from exam;
💎5.4 MAX()和MIN()
求指定列中的最大值和最小值
-- 求最大值和最小值
select max(chinese) as 语文最大值,min(math) as 数学最小值
from exam;
可以多个聚合函数使用,同时也可以使用别名
相关文章:

MySQL:表的设计原则和聚合函数
所属专栏:MySQL学习 💎1. 表的设计原则 1. 从需求中找到类,类对应到数据库中的实体,实体在数据库中表现为一张一张的表,类中的属性对应着表中的字段 2. 确定类与类的对应关系 3. 使用SQL去创建具体的表 范式࿱…...
介绍springmvc-水文
Spring MVC 是一个基于 Java 的开源 Web 框架,它是 Spring Framework 的一部分。Spring MVC 提供了一个架构,用于开发灵活、可扩展的 Web 应用程序。 Spring MVC 的主要特点包括: 基于模型-视图-控制器(MVC)的架构&am…...

uni-app学习笔记
一、下载HBuilder https://www.dcloud.io/hbuilderx.html 上述网址下载对应版本,下载完成后进行解压,不需要安装,解压完成后,点击HBuilder X.exe文件进行运行程序 二、创建uni-app项目 此处我是按照文档创建的uni-ui项目模板…...

Windows Server修改远程桌面端口
新建入站规则 填写端口 允许连接 修改远程桌面端口 winR打开注册表 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp修改PortNumber为新端口 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wi…...

界面组件Kendo UI for Vue 2024 Q2亮点 - 发布一系列新组件
随着最新的2024年第二季度发布,Kendo UI for Vue为应用程序开发设定了标准,包括生成式AI集成、增强的设计系统功能和可访问的数据可视化。新的2024年第二季度版本为应用程序界面提供了人工智能(AI)提示,从设计到代码的生产力增强、可访问性改…...

达梦数据库 逻辑备份还原
达梦的逻辑备份还原 1.背景2.要求3.实验步骤3.1 相关术语3.2 dexp逻辑导出3.2.1 使用dexp工具3.2.2 dexp相关参数含义3.2.3 四种级别导出3.2.3.1 FULL3.2.3.2 OWNER3.2.3.3 SCHEMAS3.2.3.4 TABLES 3.2.4 使用范例3.2.4.1 环境准备3.2.4.2 dexp逻辑导出 3.3 dimp逻辑导入3.3.1 使…...

Stable Diffusion绘画 | 图生图-上传重绘蒙版
上传重绘蒙版,可以弥补局部重绘的缺点,能够更精细的修改画面中的指定区域 使用PS制作的蒙版图片为耳朵下方区域,可以为图片中的女生带上不同款式的耳环。 参数配置: 调整提示词: 生成图片如下所示: 调整提…...

打开Office(word、excel、ppt)显示操作系统当前的配置不能运行此应用程序最全解决方案!
我以前用过分区助手把office从c盘挪到d盘了,从那以后office就用不了了,然后我就删了(貌似没删干净)。 最近由于有使用word的需求,所以我从学校官网找到正版软件的安装包,按照步骤重新卸载电脑中office残留…...

猫头虎 分享已解决Bug || TypeError: Cannot read property ‘map‘ of undefined 解决方案
🐯 猫头虎 分享已解决Bug || TypeError: Cannot read property map of undefined 解决方案 摘要: 今天猫头虎带大家深入探讨在前端开发中常见的一个令人头疼的问题:TypeError: Cannot read property map of undefined。这个错误通常出现在我…...

大模型快速部署,以浪潮源2.0为例
step1: 申请PAI-DSW试用 step2:魔塔社区授权 由于本地授权一直失败,于是采用了魔塔免费平台实例进行学习。 搭建好之后,打开就有相关页面了: demo搭建: 按照官方提示的步骤进行搭建,内容如下:…...
Python知识点:使用FastAI进行快速深度学习模型构建
使用FastAI构建深度学习模型非常方便,尤其是对于快速原型开发和实验。以下是一个使用FastAI构建深度学习模型的完整示例,涵盖数据准备、模型训练和评估。 安装依赖 首先,确保你安装了FastAI库和其他必要的库: pip install fast…...
Nginx配置全局https
Nginx配置全局https 要在 Nginx 中配置将 HTTP (80 端口) 请求重定向到 HTTPS (443 端口),可以在 Nginx 的配置文件中添加以下配置。假设你已经配置好了 HTTPS 相关的证书和密钥。 打开你的 Nginx 配置文件,通常是 /etc/nginx/nginx.conf。 在配置文件…...

DBAPI 如何对SQL查询出的日期字段进行统一格式转换
DBAPI 如何对SQL查询出的日期字段进行统一格式转换 mysql有一张订单表,有两个datetime类型的字段create_time update_time 新建一个API,SQL内容是查询所有数据 访问API发现日期字段默认返回时间戳格式 如果修改成自己想要的年月日格式,就要使…...

C:每日一题:字符串左旋
题目:实现一个函数,可以实现字符串的左旋 例如:ABCD左旋一个字符就是BCDA;ABCD左旋两个字符就是CDAB; 1、解题思路: 1.确定目标旋转k个字符,我们要获取字符串的长度 len,目的是根…...

深兰科技荣获2024年度金势奖“AI出海先锋品牌”金奖
近日,由金势奖组委会、凤凰网、营销国际协会等国内外知名机构、集团共同主办的“第四届未来营销大会暨锐品牌盛典”在上海举行。大会揭晓了第四届“金势奖锐品牌大赏”奖项的评选结果,深兰科技凭借自身在机器人产品出口和海外市场开拓等出海全球化发展方…...

服务器启动jar包的时候报”no main manifest attribute“异常(快捷解决)
所以,哥们,又出现问题咯.没事,我也出现了,哈哈哈哈哈,csdn感觉太麻烦了,所以搞了一篇这个. 没得事,往下看,包解决的. 希望可以帮助到各位,感谢阅览! 小手点个赞,作者会乐烂哈哈哈哈哈哈😆😆😆😆…...

部分控件的setText文案没有出现在retranslateUi()中,多语言切换不生效问题
问题:在designer中设计UI,我从其他ui文件copy了部分控件,新ui文件重新编译生成后,setText()并没有出现在新文件的retranslateUi()函数中,导致多语言切换不生效。 void retranslateUi(QWidget * …...

ubuntu系统下安装LNMP集成环境的详细步骤(保姆级教程)
php开发中集成环境的安装是必不可少的技能,而LNMP代表的是:Linux系统下Nginx+MySQL+PHP这种网站服务器架构。今天就给大家分享下LNMP的安装步骤。 1 Nginx安装 在安装Nginx前先执行下更新命令: sudo apt-get update 接下来开始安装Nginx, 提示:Could not get lock /v…...
化繁为简:揭秘中介者模式在Java设计中的魅力与力量
中介者模式是一种行为型设计模式,它通过引入一个中介者对象来简化多个对象之间的交互,从而降低它们之间的耦合度。在Java设计模式中,中介者模式扮演着重要的角色,特别是在处理复杂系统模块间的交互时。下面对Java设计模式之中介者…...

Postgresql导入矢量数据
前期准备 工具:PgAdmin,postgis-bundle Postgres安装和postgis安装可以百度别的教程。 创建数据库添加扩展 如图,使用PgAdmin创建名为shp的数据库,并在扩展item中添加postgis扩展。 添加扩展方法可以用查询工具输入以下sql语句&…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案
在大数据时代,海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构,在处理大规模数据抓取任务时展现出强大的能力。然而,随着业务规模的不断扩大和数据抓取需求的日益复杂,传统…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决
问题: pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”,…...

[拓扑优化] 1.概述
常见的拓扑优化方法有:均匀化法、变密度法、渐进结构优化法、水平集法、移动可变形组件法等。 常见的数值计算方法有:有限元法、有限差分法、边界元法、离散元法、无网格法、扩展有限元法、等几何分析等。 将上述数值计算方法与拓扑优化方法结合&#…...
Python第七周作业
Python第七周作业 文章目录 Python第七周作业 1.使用open以只读模式打开文件data.txt,并逐行打印内容 2.使用pathlib模块获取当前脚本的绝对路径,并创建logs目录(若不存在) 3.递归遍历目录data,输出所有.csv文件的路径…...

工厂方法模式和抽象工厂方法模式的battle
1.案例直接上手 在这个案例里面,我们会实现这个普通的工厂方法,并且对比这个普通工厂方法和我们直接创建对象的差别在哪里,为什么需要一个工厂: 下面的这个是我们的这个案例里面涉及到的接口和对应的实现类: 两个发…...