NF R 99-211-80是什么?fyi.能否发给领导给个简介?

基本图形本章内容:条形图、箱线图、点图饼图和扇形图直方图和核密度图6。1 条形图条形图通过垂直的或水平的条形展示了类别型变量的分布(频数)。函数barplot()的用法:barplot(height)
其中,height是一个向量或者矩阵。我们安装vcd包,是为了使用Arthritis数据集。6。1。1简单的条形图下面的示例,数据包含在vcd包分发的Arthritis数据框中。在关节炎的研究中,变量Improved记录了对每位接受了安慰剂或药物治疗的病人的治疗结果:& library(vcd)
& counts&-table(Arthritis$Improved)
None Some Marked
分析:我们看到,28个病人marked,14人部分改善,42人未改善。我们使用条形图来绘制变量counts代码6-1
简单的条形图#简单条形图
barplot(counts,main="Simple Bar Plot",xlab = "Improvement",ylab="Frequency")
#水平条形图
barplot(counts,main="Horizontal Bar Plot",xlab = "Frequency",ylab="Improvement",horiz=TRUE)
生成因素变量的条形图在无需使用table()函数将数据框Arthritis 表格化的时候,怎么才能实现呢?如果要绘制的类别变量是一个因子或有序因子,我们可以使用函数plot()来创建垂直条形图,而无需使用table()函数将数据框Arthritis 表格化。因为Arthritis$Improved是因子。代码:plot(Arthritis$Improved,main="Simple Bar Plot",xlab="Improved",ylab="Frequency")
plot(Arthritis$Improved,horiz=TRUE,main="Simple Bar Plot",xlab="Improved",ylab="Frequency")
堆砌条形图和分组条形图若height是一个矩阵而非向量。绘图结果就是一幅堆砌条形图或分组条形图。若beside=FALSE(默认值)。矩阵中每一列都将生成图中的一个条形,各列中的值将给出堆砌的”子条“的高度。若beside=TRUE。矩阵中每一列都表示一个分组,各列中的值将并列。考虑治疗类型和改善情况的列联表:代码6-2
堆砌条形图和分组条形图& library(vcd)
& counts&-table(Arthritis$Improved,Arthritis$Treatment)
Placebo Treated
#堆砌条形图
& barplot(counts,main="Stacked Bar Plot",xlab="Treatment",ylab="Frequency",col = c("red","yellow","green"),legend=rownames(counts))
#分组条形图
& barplot(counts,main="Grouped Bar Plot",xlab="Treatment",ylab="Frequency",col = c("red","yellow","green"),legend=rownames(counts),beside = TRUE)
分析:col选项添加了三种颜色。
参数legend.text为图例提供了各条形的标签(只在height为矩阵时候有用)6。1。3均值条形图可以使用数据整合函数将数据结果传递给barplot()函数,来创建均值、中位数、标准差等条形图。代码6-3
排序后的条形图&options(digits = 3)
& states&-data.frame(state.region,state.x77)
& means&-aggregate(states$Illiteracy,by=list(state.region),FUN=mean)
1 Northeast 1.00
2 South 1.74
3 North Central 0.70
4 West 1.02
#将均值从小到大排列
& means&-means[order(means$x),]
3 North Central 0.70
1 Northeast 1.00
4 West 1.02
2 South 1.74
& barplot(means$x,names.arg = means$Group.1)
& title("Mean Illiteracy Rate") #添加标题
美国各地区平均文盲率的排序条形图分析:使用title()函数与调用plot()时添加main选项等价。mean$x 是包含各条形高度的向量,而添加项names.arg=means$Group.1是为了展示标签。6。1。4 条形图的微调参数cex.names
来减少字号参数names.arg允许指定一个字符向量作为条形的标签名。代码6-4
位条形图搭配标签#增加y边界大小
par(mar=c(5,8,4,2))
#旋转条形标签
par(las=2)
counts&-table(Arthritis$Improved)
barplot(counts,main = "Threatment Outcome",horiz=TRUE,
cex.names = 0.8, #缩小字体,让标签更合适
names.arg = c("No Improvement","Some Improvement","Marked Improvement")) #修改标签文本
6。1。5棘状图(spinogram)棘状图对堆砌条形图进行了重缩放,使每个条形高度为1,每一段的高度即表示比例。棘状图由vcd()包中的函数spine()函数绘制。library(vcd)
attach(Arthritis)
counts&-table(Treatment,Improved)
spine(counts,main = "Spinogram Example")
detach(Arthritis)
关节炎的治疗效果棘状图6.2饼图饼图由由以下函数创建:pie(x,labels)其中,x是一个非负向量,表示每个扇形的面积labels是表示各扇形标签的字符型向量代码6-5
饼图#将四幅图组合成一幅图
par(mfrow=c(2,2))
slices&-c(10,12,4,16,8)
lbls&-c("US","UK","Australia","Germany","France")
pie(slices,labels = lbls,main="Simple Pie Chart")
#为饼图添加数值
pct&-round(slices/sum(slices)*100)
lbls2&-paste(lbls," ",pct,"%",sep=" ")
pie(slices,labels = lbls2,col = rainbow(length(lbls2)),main = "Pie Chart with Percentages")
library(plotrix)
pie3D(slices,labels=lbls,explode=0.1,main="3D Pie Chart")
#从表格创建饼图
mytable&-table(state.region)
lbls3&-paste(names(mytable),"\n",mytable,sep=" ")
pie(mytable,labels = lbls3,main="Pie Chart from a Table\n (with sample sizes)")
分析:rainbow()函数定义了各扇形的颜色。这里的rainbow(length(lbls2))将被解析为rainbow(5),也就是为图形提供5中颜色plotrix()包中的pie3D()函数用来创建的三维饼图。第四个图演示了如何从表格创建饼图。饼图其实让各个扇形的图的比较变得更困难,我们创造了扇形图(fan plot)在R中,扇形图是通过plotrix 包中的fan.plot()函数实现的。代码:library(plotrix)
slices&-c(10,24,4,16,8)
lbls&-c("US","UK","Australia","Germany","France")
fan.plot(slices,labels = lbls,main = "Fan Plot")
直方图如下函数创建直方图:hist(x)x是一个由数据值组成的数值向量。参数freq=FALSE表示根据概率密度而不是频数绘制的图形。参数breaks用于控制组的数量。代码6-6
直方图#将四幅图组合为一幅图
par(mfrow=c(2,2))
#简单直方图
hist(mtcars$mpg)
#指定将组数指定为12,红色填充,添加标签
hist(mtcars$mpg,breaks = 12,col="red",xlab = "Miles Per Gallon",main = "Colored histogram with 12 bins")
#保留第二幅图的颜色、组数、标签、标题设置。又叠加了一条密度曲线和轴须图
hist(mtcars$mpg,freq = FALSE,breaks = 12,col="red",xlab="Miles Per Gallon",main = "Histogram,rug plot,density curve")
rug(jitter(mtcars$mpg)) #轴须图的数据有许多结,使用代码将轴须图的数据打散。
lines(density(mtcars$mpg),col="blue",lwd=2)
#下面整个代码添加正态密度曲线和外框
x&-mtcars$mpg
h&-hist(x,breaks = 12,col="red",xlab = "Miles Per Gallon",main="Histogram with normal curve and box")
xfit&-seq(min(x),max(x),length=40)
yfit&-dnorm(xfit,mean = mean(x),sd=sd(x))
yfit&-yfit*diff(h$mids[1:2])*length(x)
lines(xfit,yfit,col="blue",lwd=2)
分析:第一幅直方图是未指定任何选项时的默认图形。第二个直方图指定将组数指定为12。第三幅图又叠加一条密度曲线和轴须图。第四幅图有一条叠加在上面的正态曲线和一个将图形围绕起来的盒型。6。4 核密度图和密度估计是用于估计随机变量概率密度函数的一种非参数的方法。语法:plot(density(x))
x是一个数值型向量。plot()函数会创建一幅新的图形,向一幅已经存在的图形上叠加一条密度曲线。可以使用lines()函数代码6-7
核密度图par(mfrow=c(2,1))
d&-density(mtcars$mpg)
#完全使用默认设置创建最简图形
d&-density(mtcars$mpg)
#添加一个标题
plot(d,main = "Kernel Density of Miles Per Gallon")
#将曲线修改为蓝色,并使用实心红色填充曲线下方的区域
polygon(d,col = "red",border = "blue")
#添加棕色的轴须图
rug(mtcars$mpg,col = "brown")
polygon()函数根据顶点的x和y坐标绘制了多边形。核密度图用于比较组间的差距,sm包可以满足这个要求。sm包中的sm.density.compare(x,factor)其中,x是一个数值型向量,factor是一个分组变量。代码6-8
可比较的核密度图library(sm)
attach(mtcars) #绑定数据框mtcars
#创建分组因子
cyl.f&-factor(cyl,levels = c(4,6,8),labels=c("4 cylinder","6 cylinder","8 cylinder"))
#绘制密度图
sm.density.compare(mpg,cyl,xlab="Miles Per Gallon")
title(main="MPG Distribution by Car Cylinders")
#通过鼠标单击图形在任意位置添加图例
colfill&-c(2:(1+length(levels(cyl.f))))
legend(locator(1),levels(cyl.f),fill = colfill)
detach(mtcars)
分析:变量cyl是一个以4、6、8编码的数值型变量。为了向图形提供值的标签,cyl转换为cyl.f的因子。函数sm.density.compare()创建了图形,一条title()语句添加了主标题。title()添加主标题创建颜色向量,colfill值为c(2,3,4),通过legend()函数向图形添加一个人图例。参数值locator(1)表示用鼠标点击想让图例出现的位置任意。levels(cyl.f)由标签组成的字符向量。参数fill = colfill使用colfill为cyl.f的每一个水平指定了一种颜色。6。5 箱线图箱线图是一项用来可视化和组间差异的绝佳图形手段。箱线图通过绘制连续型变量的五数总括:最小值、下四分位数(第25百分位数)、中位数(第50百分位数)、上四分位数(第75百分位数),描述了连续型变量的分布。代码:boxplot(mtcars$mpg,main="Box plot",ylab="Miles per Gallon")
使用并列箱线图进行跨组比较箱线图可以展示单个变量或分组变量。格式:boxplot(formula,data=dataframe)
formula 是一个公式,比如,y~A*B将为类别型变量A和B的所有水平的两两组合生成的数值型变量y的箱线图。参数varwidth=TRUE将使箱线图的宽度与其样本的大小的平方根成正比。参数horizontal=TRUE可以反转坐标轴的方向。boxplot(mpg~cyl,data=mtcars,main="Car Mileage Data",xlab="Number of Cylinders","ylab=Miles Per Gallon")
上图看出不同的组间的油耗的区别非常明显。参数notch=TRUE,可以得到含有凹槽的箱线图。boxplot(mpg~cyl,data=mtcars,notch=TRUE,varwidth=TRUE,col="red",main="Car Mileage Data",xlab="Number of Cylinders","ylab=Miles Per Gallon")
不同的汽缸数量车型油耗的含凹槽箱线图。代码6-9
两个交叉因子的箱线图#创建汽缸数量的因子
mtcars$cyl.f&-factor(mtcars$cyl,levels = c(4,6,8),labels = c("4","6","8"))
#创建变速箱类型的因子
mtcars$am.f&-factor(mtcars$am,levels = c(0,1),labels = c("auto","standard"))
#生成箱线图
boxplot(mpg~am.f*cyl.f,data=mtcars,varwidth=TRUE,col=c("gold","darkgreen"),main="MPG Distribution by Auto Type",xlab="Auto Type",ylab="Miles Per Gallon")
小提琴图小提琴图是箱线图与核密度图的结合。可以使用vioplot()包中的vioplot()函数绘制它。使用格式:vioplot(x1,x2...,names=,col=)其中,x1,x2...表示要绘制的一个或多个数值向量。参数names是小提琴图中标签的字符向量,col是指定颜色的向量。代码6-10
小提琴图library(vioplot)
x1&-mtcars$mpg[mtcars$cyl==4]
x2&-mtcars$mpg[mtcars$cyl==6]
x3&-mtcars$mpg[mtcars$cyl==8]
vioplot(x1,x2,x3,names=c("4 cyl","6 cyl","8 cyl"),col="gold")
title("Violin Plots of Miles Per Gallon",ylab="Miles Per Gallon",xlab="Number of Cylinders")
分析:图中,白点是中位数;黑色盒型的范围是下四分位点到上四分位点。细黑线表示须。外部形状为核密度估计。6。6点图点图提供了一种在简单水平刻度上绘制大量有标签值的方法。可以使用dotchart()函数来创建点图。格式:dotchart(x,labels=)
其中,x为一个数值向量,labels是由每个点的标签组成的向量。可以通过添加参数groups来选定一个因子。cex可以控制标签的大小。如:dotchart(mtcars$mpg,labels = row.names(mtcars),cex=.7,main="Gas Mileage for Car Models",xlab="Miles Per Gallon")
上图可以在同一个水平轴上观察每种车型的每加仑汽油行驶的英里数。代码6-11
分组、排序、着色后的点图#根据每加仑汽油行驶英里数对数据库进行排序,结果保存为数据框x
x&-mtcars[order(mtcars$mpg),]
#将数值向量cyl转换为一个因子
x$cyl&-factor(x$cyl)
#下面三行代码是添加一个字符型向量(color)到数据框x中,根据cyl的值,所含有的值为“red”、“blue”、"darkgreen"
x$color[x$cyl==4]&-"red"
x$color[x$cyl==6]&-"blue"
x$color[x$cyl==8]&-"darkgreen"
#各数据点的标签取自数据框的行名
dotchart(x$mpg,labels=row.names(x),cex=.7,groups=x$cyl,gcolor="black",color=x$color,pch=19,main="Gas Mileage for Car Models\ngrouped by cylinder",xlab="Miles Per Gallon")
声明:以上笔记来自《R语言实战》 【美】Robert I.Kabacoff 著
人民邮电出版社4添加评论分享收藏文章被以下专栏收录写专栏就是为了记录我的成长过程,从零开始学习数据分析。范式(数据库术语)_百度百科
清除历史记录关闭
声明:百科词条人人可编辑,词条创建和修改均免费,绝不存在官方及代理商付费代编,请勿上当受骗。
?数据库术语
(数据库术语)
范式是符合某一种级别的关系模式的集合。关系数据库中的关系必须满足一定的要求,满足不同程度要求的为不同范式。
范式内容简介
范式(,数据库的设计范式)
是符合某一种级别的的集合。构造数据库必须遵循一定的规则。在中,这种规则就是范式。中的关系必须满足一定的要求,即满足不同的范式。
目前有六种范式:(1NF)、(2NF)、(3NF)、Boyce-Codd范式()、(4NF)和(5NF)。
满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多要求的称为第二范式(2NF),其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。
下面我们举例介绍第一范式(1NF)、第二范式(2NF)和第三范式(3NF)。
在创建一个数据库的过程中,范化是将其转化为一些表的过程,这种方法可以使从数据库得到的结果更加明确。这样可能使数据库产生重复数据,从而导致创建多余的表。范化是在识别数据库中的数据元素、关系以及定义所需的表和各表中的项目等这些初始工作之后的一个细化的过程。
下面是范化的一个例子:
Customer  Item purchased   Purchase price
------------------------------------------------------------------------
Thomas Shirt $40
Maria Tennis shoes $35
Evelyn   Shirt $40
Pajaro Trousers $25
如果上面这个表用于保存物品的价格,而你想要删除其中的一个顾客,这时你就必须同时删除一个价格。范化就是要解决这个问题,你可以将这个表化为两个表,一个用于存储每个顾客及其所买物品的信息,另一个用于存储每件产品和其价格的信息,这样对其中一个表做添加或删除操作就不会影响另一个表。
范式范式类型
关系数据库中的几种设计范式
1 第一范式(1NF)
在任何一个中,第一范式(1NF)
是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库。
所谓第一范式(1NF)是指数据库的每一列都是不可分割的基本数据项,同一列中不能有多个值,即中的某个不能有多个值或者不能有重复的属性。如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。在第一范式(1NF)中表的每一行只包含一个实例的信息。
简而言之,第一范式就是无重复的列。
2 第二范式(2NF)
第二范式(2NF)
是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个或行必须可以被唯一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。这个唯一属性列被称为或主键、主码。
第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。
简而言之,第二范式就是非主属性非部分依赖于主关键字。
3 第三范式(3NF)
满足第三范式(3NF)
必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。
例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在图3-2的员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。
简而言之,第三范式就是属性不依赖于其它非主属性。
是最终范式,消除了4NF中的连接依赖。
软道范式是对数据库进行优化的原则 。
(欢迎广大读者补充更正以上信息)
数据库设计三大范式应用实例剖析
数据库的是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的、结构明晰的;同时,不会发生插入(insert)、删除(delete)和更新(update)操作异常。反之则是乱七八糟,不仅给数据库的编程人员制造麻烦,而且面目可憎,可能存储了大量不需要的。
是不是很难懂呢?非也,大学教材上给我们一堆我们当然看不懂,也记不住。所以我们很多人就根本不按照范式来设计数据库。
实质上,用很形象、很简洁的话语就能说清楚道明白。本文将对范式进行通俗地说明,并以笔者曾经设计的一个简单论坛的数据库为例来讲解怎样将这些范式应用于实际工程。
范式范式说明
Ⅰ第一范式(1NF):
数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成,包括整型、、字符型、逻辑型、日期型等。
定义:如果一个关系模式R的所有属性都是不可分的基本,则R属于1NF。
例如,下面的数据库表是符合第一范式的:
字段1 字段2 字段3 字段4
而这样的数据库表是不符合第一范式的:
字段1 字段2 字段3 字段4
字段3.1 字段3.2
很显然,在当前的任何(DBMS)中,谁也不可能做出不符合第一范式的数据库,因为这些DBMS不允许你把数据库表的一列再分成二列或多列。因此,想在现有的DBMS中设计出不符合第一范式的数据库都是不可能的。
Ⅱ 第二范式(2NF):
数据库表中不存在非关键字段对任一段的(部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况),也即所有非关键字段都完全依赖于任意一组候选关键字。
假定选课关系表为SelectCourse(学号,姓名,年龄,课程名称,成绩,学分),关键字为组合关键字(学号,课程名称),因为存在如下决定关系:
(学号,课程名称) → (姓名,年龄,成绩,学分)
这个数据库表不满足第二范式,因为存在如下决定关系:
(课程名称) → (学分)
(学号) → (姓名,年龄)
即存在组合关键字中的字段决定非关键字的情况。
由于不符合2NF,这个选课关系表会存在如下问题:
(1) 数据冗余:
同一门课程由n个学生选修,&学分&就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。
(2) 更新异常:
若调整了某门课程的学分,数据表中所有行的&学分&值都要更新,否则会出现同一门课程学分不同的情况。
(3) 插入异常:
假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有&学号&关键字,课程名称和学分也无法记录入数据库。
(4) 删除异常:
假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。
把选课关系表SelectCourse改为如下三个表:
学生:Student(学号,姓名,年龄);
课程:Course(课程名称,学分);
选课关系:SelectCourse(学号,课程名称,成绩)。
这样的数据库表是符合第二范式的, 消除了数据冗余、更新异常、插入异常和删除异常。
另外,所有单关键字的数据库表都符合第二范式,因为不可能存在组合关键字。
Ⅲ 第三范式(3NF):
在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的则符合第三范式。所谓传递函数依赖,指的是如果存在&A → B → C&的决定关系,则C传递函数依赖于A。因此,满足第三范式的数据库表应该不存在如下依赖关系:
关键字段 → 非关键字段x → 非关键字段y
假定学生关系表为Student(学号,姓名,年龄,所在学院,学院地点,学院电话),关键字为单一关键字&学号&,因为存在如下决定关系:
(学号) → (姓名,年龄,所在学院,学院地点,学院电话)
这个数据库是符合2NF的,但是不符合3NF,因为存在如下决定关系:
(学号) → (所在学院) → (学院地点,学院电话)
即存在非关键字段&学院地点&、&学院电话&对关键字段&学号&的传递函数依赖。
它也会存在数据冗余、更新异常、插入异常和删除异常的情况,读者可自行分析得知。
把学生关系表分为如下两个表:
学生:(学号,姓名,年龄,所在学院);
学院:(学院,地点,电话)。
这样的数据库表是符合第三范式的,消除了数据冗余、更新异常、插入异常和删除异常。
Ⅳ鲍依斯-科得范式(BCNF):
在第三范式的基础上,数据库表中如果不存在任何字段对任一候选关键字段的则符合第三范式。
假设仓库管理关系表为StorehouseManage(仓库ID,存储物品ID,ID,数量),且有一个管理员只在一个仓库工作,一个仓库可以存储多种物品。这个数据库表中存在如下决定关系:
(仓库ID,存储物品ID) →(管理员ID,数量)
(管理员ID,存储物品ID) → (仓库ID,数量)
所以(仓库ID,存储物品ID)和(管理员ID,存储物品ID)都是StorehouseManage的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:
(仓库ID) → (管理员ID)
(管理员ID) → (仓库ID)
即存在关键字段决定关键字段的情况,所以其不符合BCNF范式。它会出现如下异常情况:
(1) 删除异常:
当仓库被清空后,所有&存储物品ID&和&数量&信息被删除的同时,&仓库ID&和&管理员ID&信息也被删除了。
(2) 插入异常:
当仓库没有存储任何物品时,无法给仓库分配管理员。
(3) 更新异常:
如果仓库换了管理员,则表中所有行的管理员ID都要修改。
把仓库管理关系表分解为二个关系表:
仓库管理:StorehouseManage(仓库ID,管理员ID);
仓库:Storehouse(仓库ID,存储物品ID,数量)。
这样的数据库表是符合BCNF范式的,消除了删除异常、插入异常和更新异常。
Ⅴ 第四范式(4NF):
关系模式R&U,F&∈1NF,如果对于R对于R的每个非平凡多值依赖X→→Y(Y不属于X),X都含有候选码,则R∈4NF。4NF就是限制关系模式的属性之间不允许有非平凡且非函数依赖的多值依赖。显然一个关系模式是4NF,则必为BCNF。
Ⅵ 第五范式(5NF):
是最终范式,消除了4NF中的连接依赖。
VII DK范式(DKNF):在值域上定义上的范式。
VIII 第六范式(6NF):目前关系型数据库最高范式。所有第六范式的关系同时满足第5范式与DK范式。
范式范式应用
例如,我们来逐步搞定一个论坛的数据库,有如下信息:
1. 用户:用户名,email,主页,电话,联系地址
2. 帖子:发帖标题,发帖内容,回复标题,回复内容
第一次我们将数据库设计为仅仅存在表:
用户名 email 主页 电话 联系地址 发帖标题 发帖内容 回复标题 回复内容
这个数据库表符合第一范式,但是没有任何一组能决定数据库的整行,唯一的段用户名也不能完全决定整个元组。
我们需要增加&发帖ID&、&回复ID&字段,即将表修改为:
用户名 email 主页 电话 联系地址 发帖ID 发帖标题 发帖内容 回复ID 回复标题 回复内容
这样数据表中的关键字(用户名,发帖ID,回复ID)能决定整行:
(用户名,发帖ID,回复ID) → (email,主页,电话,联系地址,发帖标题,发帖内容,回复标题,回复内容)
但是,这样的设计不符合第二范式,因为存在如下决定关系:
(用户名) → (email,主页,电话,联系地址)
(发帖ID) → (发帖标题,发帖内容)
(回复ID) → (回复标题,回复内容)
即非关键字段于候选关键字段,很明显,这个设计会导致大量的数据冗余和操作异常。
我们将数据库表分解为(带下划线的为关键字):
1. 用户信息:用户名,email,主页,电话,联系地址
2. 帖子信息:发帖ID,标题,内容
3. 回复信息:回复ID,标题,内容
4. 发贴:用户名,发帖ID
5. 回复:发帖ID,回复ID
这样的设计是满足第1、2、3范式和BCNF范式要求的,但是这样的设计是不是最好的呢?
观察可知,第4项&发帖&中的&用户名&和&发帖ID&之间是1:N的关系,因此我们可以把&发帖&合并到第2项的&帖子信息&中;第5项&回复&中的&发帖ID&和&回复ID&之间也是1:N的关系,因此我们可以把&回复&合并到第3项的&回复信息&中。这样可以一定量地减少数据冗余,新的设计为:
1. 用户信息:用户名,email,主页,电话,联系地址
2. 帖子信息:用户名,发帖ID,标题,内容
3. 回复信息:发帖ID,回复ID,标题,内容
数据库表1显然满足所有范式的要求;
数据库表2中存在非关键字段&标题&、&内容&对关键字段&发帖ID&的部分函数依赖,即不满足第二范式的要求,但是这一设计并不会导致数据冗余和操作异常;
数据库表3中也存在非关键字段&标题&、&内容&对关键字段&回复ID&的部分函数依赖,也不满足第二范式的要求,但是与数据库表2相似,这一设计也不会导致数据冗余和操作异常。
由此可以看出,并不一定要强行满足范式的要求,对于1:N关系,当1的一边合并到N的那边后,N的那边就不再满足第二范式了,但是这种设计反而比较好!
对于M:N的关系,不能将M一边或N一边合并到另一边去,这样会导致不符合范式要求,同时导致操作异常和数据冗余。
对于1:1的关系,我们可以将左边的1或者右边的1合并到另一边去,设计会导致不符合范式要求,但是并不会导致操作异常和数据冗余。
满足范式要求的数据库设计是结构清晰的,同时可避免数据冗余和操作异常。这并不意味着不符合范式要求的设计一定是错误的,在数据库表中存在1:1或1:N关系这种较特殊的情况下,合并导致的不符合范式要求反而是合理的。
在我们设计数据库的时候,一定要时刻考虑范式的要求。
消除决定因素 | 1NF
非码的非平凡 | ↓ 消除非主属性对码的部分函数依赖
函数依赖 | 2NF
| ↓ 消除非主属性对码的传递函数依赖
| ↓ 消除主属性对码的部分和传递函数依赖
| ↓ 消除非平凡且非函数依赖的
| ↓消除不是由所蕴含的连接依赖
数据库系统原理.周志逵 郭贵锁:清华大学出版社,2008年11月
.网易[引用日期]
中国电子学会(Chinese Instit...
提供资源类型:内容
清除历史记录关闭

我要回帖

更多关于 按揭房能否公证给老婆 的文章

 

随机推荐