MYSQL<四>
-- ########## 01、ER关系 ########## -- ER关系(逻辑描述)
-- A:E---Entity简写,实体,具有相同属性(特征)的对象归为同一实体
-- Attribute属性,描述实体具有的特征,一个实体可以有若干个属性来描述
-- B:R---Relationship简写,关系/联系,数据对象彼此之间的互相关联的关系 -- ER关系常见的三种形式:
-- 1、一对一关系(1:1):例如:夫妻关系、一个国家只有一个最高领导人、向日葵...
-- 2、一对多关系(1:n):例如:一把锁有多把钥匙、一个房子有多个门、一个皇帝有多个太监、一个部门有多个员工...
-- 3、多对多关系(m:n):例如:参加招聘会的企业和同学、学生选课、饭桌上的菜和吃菜的人... -- ########## 02、数据库设计 ##########
-- 设计的过程不是一步到位的,也不可能一步到位,都是一个反复迭代的过程 -- 需求:商城里会员顾客购买若干数量的商品
-- 提供的数据如下:
-- 顾客编号为1的顾客张三购买了3个商品编号为123的A商品
-- 顾客编号为2的顾客李四购买了4个商品编号为456的B商品
-- 顾客编号为1的顾客张三购买了3个商品编号为123的A商品(数据来自不同渠道)
-- 顾客编号为3的顾客王五购买了5个商品编号为123的A商品
-- 顾客编号为1的顾客张三购买了2个商品编号为456的B商品
-- ..... -- 分析:这可能就是业务提供方描述的一个场景,数据库设计时,会从中挖掘出很多信息
-- 数据整理:去除无效的数据,比如:去除重复的数据(可能来自不同的渠道,但是其实描述的是相同的数据内容) -- 广大开发人员在长期的数据库设计过程中归纳整理了几个称为【范式】的东西
-- 【第1范式(1NF)】为了保证表中的行的数据是唯一的,属性是原子的。
-- 也就是说,行的唯一性通过在表中定义一个唯一的主键来实现
-- 注意:这里说的唯一的主键,没有说主键只能建立在一个字段上 CREATE TABLE order_1nf
(
orderid INT,
productid INT,
quantity INT,
customerid INT,
customername VARCHAR(10) NOT NULL,
productname VARCHAR(20) NOT NULL,
PRIMARY KEY(orderid, productid)
);
DESC order_1nf; -- 【第2范式(2NF)】首先数据必须满足第1范式,其次要求非键属性(Nonkey Attribute)和候选键之间必须满足一定的条件。
-- 也就是说,一个非键属性不能只完全函数依赖于候选键的一部分。
-- 分析:order_1nf表中,customerid这个非键属性只依赖于主键(候选键)(orderid, productid)的一部分orderid,所以,需要把order_1nf表进行分解
CREATE TABLE order_2nf
(
orderid INT,
customerid INT,
customername VARCHAR(10) NOT NULL,
PRIMARY KEY(orderid)
);
CREATE TABLE orderdetail_2nf
(
orderid INT,
productid INT,
quantity INT,
PRIMARY KEY(orderid)
);
CREATE TABLE product_2nf
(
productid INT,
productname VARCHAR(20) NOT NULL,
PRIMARY KEY(productid)
); -- 【第3范式(3NF)】首先数据必须满足第2范式,其次要求所有的非键属性必须非传递依赖于候选键。
-- 也就是说,一个非键属性不能依赖于其他的非键属性。
-- 分析:order_2nf表中,customername依赖于customerid这个非键属性,所以,需要把order_2nf表进行分解
CREATE TABLE order_3nf
(
orderid INT,
customerid INT,
PRIMARY KEY(orderid)
);
CREATE TABLE customer_3nf
(
customerid INT,
customername VARCHAR(10) NOT NULL,
PRIMARY KEY(customerid)
);
CREATE TABLE orderdetail_3nf
(
orderid INT,
productid INT,
quantity INT,
PRIMARY KEY(orderid)
);
CREATE TABLE product_3nf
(
productid INT,
productname VARCHAR(20) NOT NULL,
PRIMARY KEY(productid)
); -- 注意:实际开发中,一般必须达到第2范式及以上,不过有时处于操作数据效率的考虑,设计时也会使用第2范式的设计(即包含了一些冗余) -- 需求:设计 学生选课的数据库设计
-- 学生可以选择多门课程,一门课程可以有多个学生,一个老师可以带多门课程,一门课程只能由一个老师来带,每个学生选的课程有一个相应的课程成绩
-- 分析:
-- 实体:学生、课程、老师、成绩(这四个名词拿出来作为候选实体)
-- 实体间的关系:"一个老师可以带多门课程,一门课程只能由一个老师来带"这句话描述了课程 和 老师 之间的关系是多对一的关系
-- "学生可以选择多门课程,一门课程可以有多个学生"这句话描述了 学生 和 课程之间的关系是多对多的关系
-- "每个学生选的课程有一个相应的课程成绩"这句话读起来 成绩 像是 课程的一个属性,并且是一个学生的一门课程的一个成绩,
-- 结合上述应该要先解决多对多的关系,再看这个成绩怎么设计 -- 首先设计较为独立的实体
-- 老师信息实体
CREATE TABLE teacherinfo
(
-- 老师编号
teacherid INT AUTO_INCREMENT PRIMARY KEY,
-- 老师姓名
teachername VARCHAR(10) NOT NULL,
-- 老师性别
teachergender ENUM('男', '女') NOT NULL,
-- 老师年龄
teacherage INT NOT NULL
);
-- 学生信息实体
CREATE TABLE studentinfo
(
-- 学生编号
studentid INT AUTO_INCREMENT PRIMARY KEY,
-- 学生姓名
studentname VARCHAR(10) NOT NULL,
-- 学生性别
studentgender ENUM('男', '女') NOT NULL,
-- 学生年龄
studentage INT NOT NULL
); -- 接着设计一对多的关系,可以在作为多的实体中添加作为一的实体的主键作为非键属性的值
-- 也可以在作为一的实体中添加作为多的实体的主键作为非键属性的值
-- 显然,前者操作起来比较简单,也是一对多关系的经典设计方式 -- 课程信息实体
CREATE TABLE courseinfo
(
-- 课程编号
courseid INT AUTO_INCREMENT PRIMARY KEY,
-- 课程名称
coursename VARCHAR(10) NOT NULL,
-- 老师编号
teacherid INT NOT NULL
); -- 最后考虑多对多的关系,首先考虑套用一下一对多的关系的设计,在courseinfo表中放入studentinfo表的主键,在studentinfo表中放入courseinfo表的主键
-- 这样的设计有一个问题,作为学生信息,并不确定有多少课程被选,即无法确定多个课程主键的数量,当然写在一个字段中也可以,但是操作又很麻烦
-- 同样,作为课程信息,也不确定有多少学生选择
-- 既然考虑这两个实体中都要放入对方的主键作为属性使用,这里不妨制作一个独立的关系实体,包含有着两个实体的主键作为属性,即可轻松实现多对多的关系
-- 而且,这个独立的关系实体还可以包含有和多对多关系相关的其他属性,比如:成绩 -- 成绩信息实体(学生 和 课程 多对多 关联关系表)
CREATE TABLE scoreinfo
(
-- 成绩编号
scoreid INT AUTO_INCREMENT PRIMARY KEY,
-- 学生编号
studentid INT NOT NULL,
-- 课程编号
courseid INT NOT NULL,
-- 成绩分数
score DECIMAL(4, 1) NOT NULL
); -- ########## 03、汇总数据(进阶) ########## -- 模拟数据
INSERT INTO scoreinfo VALUES(NULL, 1, 1, 60), (NULL, 1, 2, 90), (NULL, 1, 3, 80), (NULL, 1, 4, 70), (NULL, 1, 5, 40),
(NULL, 2, 1, 70), (NULL, 2, 2, 50), (NULL, 2, 3, 70), (NULL, 2, 4, 30), (NULL, 2, 5, 90),
(NULL, 3, 1, 55), (NULL, 3, 2, 65), (NULL, 3, 3, 75),
(NULL, 4, 1, 87), (NULL, 4, 2, 63), (NULL, 4, 4, 28); SELECT * FROM scoreinfo; -- 需求:获取每个同学的成绩总分和成绩平均分
-- 思路:因为每个同学可能有多门课程的成绩,所以这里需要基于学生编号进行分组,并使用聚合函数
SELECT studentid AS 学生编号, SUM(score) AS 成绩总分, AVG(score) AS 成绩平均分
FROM scoreinfo GROUP BY studentid; -- 需求:列出每门功课的最高分、最低分,该门功课的总分、该门功课的平均分
-- 思路:因为每门功课可能对应多个学生的成绩,所以这里需要基于课程编号进行分组,并使用聚合函数
SELECT courseid AS 课程编号, MAX(score) AS 最高分, MIN(score) AS 最低分, SUM(score) AS 总分, AVG(score) AS 平均分
FROM scoreinfo GROUP BY courseid; -- 需求:列出平均分高于65分的同学的学生编号及其平均分
-- 思路:首先想到的是使用分组子句(GROUP BY) 和 筛选条件子句(WHERE) -- 1、语义错误:先对scoreinfo这个集合进行了条件筛选,把65分以上的成绩都留下来了,再按学生编号进行分组
SELECT studentid AS 学生编号, AVG(score) AS 平均分
FROM scoreinfo WHERE score > 65 GROUP BY studentid; -- 2、语法错误:参照顺序图,因为WHERE子句先于GROUP BY子句执行,所以在WHERE子句中无法提前使用聚合函数
-- 错误代码: 1111 Invalid use of group function
SELECT studentid AS 学生编号, AVG(score) AS 平均分
FROM scoreinfo WHERE AVG(score) > 65 GROUP BY studentid; -- 正确写法:引入 HAVING 子句,对于分组后的数据进行条件筛选
SELECT studentid AS 学生编号, AVG(score) AS 平均分
FROM scoreinfo
GROUP BY studentid
HAVING AVG(score) > 65; -- 注意:
-- 1、WHERE子句关注的是行的记录的条件筛选
-- 2、HAVING子句关注的是组的记录的条件筛选 SELECT * FROM scoreinfo HAVING score > 70;
-- 上句可以理解为:
SELECT * FROM scoreinfo GROUP BY scoreid HAVING score > 70;
-- 下面两句可以理解为:因为按照scoreid这个主键进行分组,每组就是一条记录,对这一条记录使用聚合函数还是它自身
SELECT * FROM scoreinfo GROUP BY scoreid HAVING AVG(score) > 70;
SELECT * FROM scoreinfo GROUP BY scoreid HAVING SUM(score) > 70;
-- 也就等价于
SELECT * FROM scoreinfo WHERE score > 70; -- 需求:列出单科课程(课程编号)对应的所有同学(多行显示同学编号)
-- 如下写法不正确,因为这样分组后select获取的是每一组的第一条记录
-- 思考:为什么到处使用分组?
SELECT courseid AS 课程编号, studentid AS 学生编号
FROM scoreinfo
GROUP BY courseid; -- 正确写法
SELECT courseid AS 课程编号, studentid AS 学生编号
FROM scoreinfo
ORDER BY courseid;
-- 或者
SELECT courseid AS 课程编号, studentid AS 学生编号
FROM scoreinfo
ORDER BY courseid, studentid; -- 需求:列出单科课程(课程编号)对应的所有同学(单行显示同学编号,多个编号之间以逗号连接)
-- 思路:首先考虑分组,分组后select时使用字符函数CONCAT,但是这样拼接的是每一组的第一条记录中studentid
SELECT courseid AS 课程编号, CONCAT(studentid, ',') AS 学生编号
FROM scoreinfo
GROUP BY courseid; -- 到MySQL手册中找灵感,查找了一下和GROUP BY子句相关的内容,看到GROUP_CONCAT(expr) :该函数返回带有来自一个组的连接的非NULL值的字符串结果。
SELECT courseid AS 课程编号, GROUP_CONCAT(studentid) AS 学生编号
FROM scoreinfo
GROUP BY courseid; -- 需求:列出单科课程(课程编号)对应的学生人数
SELECT courseid AS 课程编号, COUNT(studentid) AS 选择该门课程的学生人数
FROM scoreinfo
GROUP BY courseid; -- 需求:列出单科课程(课程编号)对应的学生人数,并进行总计
-- 思路:总计操作使用 WITH ROLLUP 子句
SELECT courseid AS 课程编号, COUNT(studentid) AS 选择该门课程的学生人数
FROM scoreinfo
GROUP BY courseid
WITH ROLLUP; -- 需求:列出单科课程(课程编号)对应的所有学生(单行显示学生编号),并进行总人数的统计(单行显示学生编号)
SELECT courseid AS 课程编号, GROUP_CONCAT(studentid) AS 选择该门课程的学生编号
FROM scoreinfo
GROUP BY courseid
WITH ROLLUP;
MYSQL<四>的更多相关文章
- Hadoop 中利用 mapreduce 读写 mysql 数据
Hadoop 中利用 mapreduce 读写 mysql 数据 有时候我们在项目中会遇到输入结果集很大,但是输出结果很小,比如一些 pv.uv 数据,然后为了实时查询的需求,或者一些 OLAP ...
- mysql每秒最多能插入多少条数据 ? 死磕性能压测
前段时间搞优化,最后瓶颈发现都在数据库单点上. 问DBA,给我的写入答案是在1W(机械硬盘)左右. 联想起前几天infoQ上一篇文章说他们最好的硬件写入速度在2W后也无法提高(SSD硬盘) 但这东西感 ...
- LINUX篇,设置MYSQL远程访问实用版
每次设置root和远程访问都容易出现问题, 总结了个通用方法, 关键在于实用 step1: # mysql -u root mysql mysql> Grant all privileges o ...
- nodejs进阶(6)—连接MySQL数据库
1. 建库连库 连接MySQL数据库需要安装支持 npm install mysql 我们需要提前安装按mysql sever端 建一个数据库mydb1 mysql> CREATE DATABA ...
- MySQL高级知识- MySQL的架构介绍
[TOC] 1.MySQL 简介 概述 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一种关联数据库管理系统,将数据保存在不同的表中,而 ...
- 闰秒导致MySQL服务器的CPU sys过高
今天,有个哥们碰到一个问题,他有一个从库,只要是启动MySQL,CPU使用率就非常高,其中sys占比也比较高,具体可见下图. 注意:他的生产环境是物理机,单个CPU,4个Core. 于是,他抓取了CP ...
- 我的MYSQL学习心得(一) 简单语法
我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...
- Entity Framework Core 实现MySQL 的TimeStamp/RowVersion 并发控制
将通用的序列号生成器库 从SQL Server迁移到Mysql 遇到的一个问题,就是TimeStamp/RowVersion并发控制类型在非Microsoft SQL Server数据库中的实现.SQ ...
- Docker笔记一:基于Docker容器构建并运行 nginx + php + mysql ( mariadb ) 服务环境
首先为什么要自己编写Dockerfile来构建 nginx.php.mariadb这三个镜像呢?一是希望更深入了解Dockerfile的使用,也就能初步了解docker镜像是如何被构建的:二是希望将来 ...
- 当忘记mysql数据库密码时如何进行修改
因为长时间没有使用数据库了,或者把密码改完之后就忘了数据库密码,不能正常进入数据库,也无法修改密码,有一个简单的常用修改密码方式: 1.首先找到和打开mysql.exe和mysqld.exe所在的文件 ...
随机推荐
- sql server 字符串拆分
最近项目调取存储的时候直接传入string 作为in的查询范围,结果报错了,深思之后才发现,数据库对于传进来的String,并不是我们想的直接可以作为参数,而是作为一个整体,而in是需要一个类似arr ...
- 使用pthread下的mutex与cond_var模拟windows下的event几个接口
两个版本的链接: https://github.com/neosmart/pevents https://github.com/moya-lang/Event 第一个版本能够模拟等待多个事件中的一个触 ...
- zabbix没有10051端口解决
1.查看zabbix的日志 [root@bogon ldap]# cat /tmp/zabbix_server.log '/var/lib/mysql/mysql.sock' (2) 2848:201 ...
- three.js中物体旋转实践之房门的打开与关闭
看这篇博客,默认你已经知道了3D模型实现三维空间内旋转的实现方式(矩阵.欧拉角.四元数). ok,下面正式切入主题,房门的打开和关闭,先上图: 正如你所看到的那样,这个“房门”已经被打开了. 一.th ...
- java课堂疑问解答与思考1
问题一 Java类中只能有一个公有类吗?用Eclipse检测以下程序是否正确.是否在接口中同样适用. 答:一个源文件里必须稚嫩发有一个公有类,名称必须与文件名一致.以上程序经过编译没有提示错误.jav ...
- java带图形界面的五子棋
Main: package BlackWhite; import java.awt.BorderLayout; import java.awt.Color; import java.awt.FlowL ...
- 【VS开发】【图像处理】基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
基于灰度世界.完美反射.动态阈值等图像自动白平衡算法的原理.实现及效果 白平衡是电视摄像领域一个非常重要的概念,通过它可以解决色彩还原和色调处理的一系列问题.白平衡是随着电子影像再现色彩真实 ...
- lua基础学习(二)
一,Lua变量 1.lua变量的三种类型:全局变量,局部变量,表中的域 Lua 中的变量全是全局变量,那怕是语句块或是函数里,除非用 local 显式声明为局部变量. 局部变量的作用域为从声明位置 ...
- mac下mysql重置密码及使用用户和密码登陆
回车后 登录管理员权限 sudo su回车后输入以下命令来禁止mysql验证功能 ./mysqld_safe --skip-grant-tables &回车后mysql会自动重启(偏好设置中m ...
- HDU 1087 Super Jumping! Jumping! Jumping! (动态规划、最大上升子序列和)
Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 ...