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所在的文件 ...
随机推荐
- 【DSP开发】【VS开发】MUX和DEMUX的含义
MUX和DEMUX Mux 是 Multiplex 的缩写,意为"多路传输",其实就是"混流"."封装"的意思,与"合成" ...
- 【转帖】如何看待 HTTP/3 ?
如何看待 HTTP/3 ? https://mp.weixin.qq.com/s/fC10Cyj6xjjwOCnqxX-Dvg 车小胖的公众号 转帖学习一下. 原创: 车小胖谈网络 车小胖谈网络 20 ...
- 【7.9校内test】T2 极值问题
这个题真的,毫无思路的说,但是我们会打表啊: lz的打表之路: 当然是手写一个暴力啦(*^▽^*)! 然后滚去配置lemon测试一下暴力可以得多少分qwq: 是的40分呢! 然后其实看上面也能看出来一 ...
- HDU-5201 The Monkey King
题目描述 \(m\)个猴子分\(n\)个桃,要求第一个猴子的桃数严格大于其他猴子,问有多少种分法对\(1e9+7取模(\%1e9+7)\) Input \(1≤T≤25 ,1≤n,m≤100000\) ...
- js知识点——2之navigator
navigator(领航者) 1.appCodeName(返回浏览器的代码名) var x= navigator; document.write("CodeName:"+x.app ...
- Layui数据表格模型
视图模型 package com.meiyou.model; import org.springframework.context.annotation.Bean; import java.io.Se ...
- Pycharm Debug 问题
Pycharm debug 出现如下问题 Connected to pydev debugger (build 181.4668.75) Traceback (most recent call las ...
- ImportError: Could not import PIL.Image.
pip install pillow
- django1.9安装以及使用
安装setuptoolswget --no-check-certificate https://pypi.python.org/packages/69/56/f0f52281b5175e3d9ca86 ...
- NOIP2017 时间复杂度 大模拟
再写一道大模拟题. 由于是限时写的,相当于考场代码,乱的一批. 题目链接:P3952 时间复杂度 先记几个教训: 字符串形式的数字比较大小老老实实写函数,字典序都搞错几次了 栈空的时候不但pop()会 ...