数据库设计之问卷模块的设计1

这两个星期在设计一个问卷调查的数据库,现在做一番总结。

平时作为用户,感觉很简单的一个模块,现在参与设计,虽然感觉还有无数不完善的地方,但是设计的时候,还是考虑了很多很多。

问卷模块的设计
最主要的几个实体就是:问卷、试题、选项、试题类型


问卷与试题是多对多的关系,采用关联表
将问卷与试题看做一个整体,称为卷题,卷题与选项是一对多关系,所以采用选项持有一个问卷id和试题id

试题与试题类型之间到是多对一关系,采用试题持有试题类型id


试题类型的难点是层级结构,层级结构采用的是增加一个pid字段来表示,父子关系
然后增加一个varchar类型的path方便查询,path会记录从顶层节点,到该节点的路径。
在查询直接子节点是用where pid = xxx即可

查询所有子节点,采用like对path字段进行匹配。


涉及到的关键问题
1.由于问卷相当于是引用试题库的试题,如果其中一个问卷修改了或者删除了某个试题影响其他问卷怎么处理?
(1)由于问卷是引用的试题,所以从问卷中删除试题,只是删除关联表中的记录,试题本身并不会被物理删除。当然由于选项是单独问卷+试题独立存储的,应该删去。
(2)关于修改的处理。给出两种接口
①关联修改。修改以后,所有引用了这个题目的地方都会被一起修改。
②独立修改。修改以后相当于是新建了一个试题,并且原本的选项也会复制,并且关联到新建的试题上。


2.既然独立修改如此麻烦,为什么不采用所有的问卷的试题独立存放?
(1)如果有许多问卷引用了一些一样的问题,会造成大量冗余。而且如果从其他试卷已有的题目中导入问题,一样会很麻烦。
(2)没有办法实现关联修改,很难改动一个地方,实现多个试卷的更改。


3.为什么试题的选项要采用,单独一个试卷的某个试题存放一份。而不是某个试题存放一份。

如果选项由试题完全决定,那么如果两个题,题目一样,选项不一样,就要算作两个题,如果将选项再加上问卷的区分,可以提供更大的灵活性。

并且分数与选项是一一对应的,而就算是同一道题,相同的选项,在不同的问卷中,分数也可能不同,提供这样灵活性是有必要的。


4.试题录入的选择
试题录入主要分为,试题基本信息(比如题目内容)与选项的录入(分值包含在不同的选项之中)
(1)手动录入
分开基本信息和选项
(2)从其他试卷导入
导入过来的试题,用户要修改基本信息会有上面提到的两种修改的不同。
但是由于选项是每个试卷的每个题目独有的,所以随意修改不会影响其他试卷。
(3)在题库中任意检索录入
由于我们采用的选项存储结构是,选项与问卷+试题相关,如果只是检索题库中题目,复制过来没有选项,还要输入选项,还是很麻烦。
这个时候我们可以完善(2)的功能,使得用户可以先以试卷选择,再任意选择题目,从而弥补(3)的不足。


5.新增问卷
新建一份问卷,需要填写基本信息、新建试题、为试题增加选项、新增结果标签。
还在新建试题的时候,由于需要实时显示已经添加的试题,与试题的选项。
要显示已经添加的东西有两种方式
(1)将已经添加的试题、选项存储在前端的表格里面什么的,然后在保存问卷的时候,再先存储问卷,取得问卷id,然后将试题,取得试题id,然后将试题与问卷关联,然后再存选项,然后再填写选项的问卷id和试题id。
(2)开始新建问卷的时候就,保存一个问卷的记录到数据库,然后新建问题的时候,已经有问卷id了,然后直接存试题,取得试题id然后,添加问卷-试题关联,然后已经添加的试题就可以通过查表显示出来了,选项同理。
但是这样有一个缺点,如果用户点进来,就放弃编辑,你还是建立了一个问卷的记录,但是取消按钮是不能发送一个消息去删除数据库的记录的,就算可以,用户也可能去点右上角的×从而退出。
(3)采用分页
把一个很大的新建问卷页面拆分成若干页面。第一个页面,只有问卷的基本信息,当用户选择保存了才会新建一条问卷记录并跳转到下一个页面。
这样对于问卷,确实有一个保存并进入下一步才会真的产生一个问卷记录,用户体验会好很多。


6.评分的处理
这个打分的逻辑,完全就是靠数据库来实现的,从而减轻了Java程序的负担。
方法是,将选项的每一种可能对应的分值,全部存下来。
这样到时候直接匹配就能得到分值,从而不需要Java程序再去做逻辑上的判断。
举个例子,一个多选题,给出了A,B,C三个选项。
你的答案里面会有A,B,C,AB,AC,BC,ABC,将所有的可能与对应的分值存入数据库。
然后给选项加入一个IS_SHOW属性,表示在题目打印的时候显示哪些。
比如这一道,就只显示A,B,C。
然后根据用户的作答去匹配选项就能得到用户的分值。


7.修改履历表
这个模块主要是对于每一个修改(增、删、改)都进行记录。
我的想法是,
(1)按照用户的体验进行记录
比如用户创建一个问卷,在之中有创建了一道题,并且创建了5个选项。
这里所有都会记录。
但是删除一个问卷,虽然同时也删除了题目记录和选项,但是只会记录删除了问卷
从一个问卷导入若干题目,也只会记录导入题
(2)所有的修改都是存放在varchar里面的。但是在拼接这个动作的时候如果直接将整个语句拼接,会很繁琐。所以我采用的办法是区分问卷、试题、选项3个级别,给三个接口,填入不同的参数,来区分操作人,操作方式(新增、编辑、删除)。
同时额外提供一个直接书写整个语句的接口,以便于以后扩展记录一些额外操作用。
比如调整一个问卷中的两个试题的顺序这个动作。


目前还没有实现的
1.结果标签实体
这个结果标签就是说,用户得到多少分可以给用户打的标签。
举个例子,考试,100-80 优 79-60 良 60-0 不及格
这个优、良、不及格就是标签。
这个模块其实完全类似于试题。
因为这个标签拥有自身的类型,这个类型也要实现层级结构。
其次标签与问卷是多对多关系,也要用关联表实现。


2.试题序号
首先,试题在题库中确实有主键id,但是由于数据库本身的特性,删除了一些记录,后面的增长还是会从已经出现过的开始,并不会从当前有的开始。
比如1,2,3,。我现在删除了3,下一个记录id就会是4,不会是3。
其次,同一道题目,在不同试卷中本来就是不同的。
所以要单独维护一个试题在问卷中的,单独的编号。
这里有几个难题
(1)新插入的试题编号
我目前想到的办法是,插入之前查一下有多少试题,然后取得应该作为几号。
(2)试题的编号变动
比如,插入一个试题到中间,或者删除一道题,其他的编号都要变动。


3.填空题
填空题如果是,根据值取范围来得分还好说,本质上可以当做选择题。计算分的时候用Java代码实现得分逻辑即可。


4.父子试题、选项与隐藏试题
父试题没有实际的内容,只是起到一个归类的作用,实际的题目还是子试题。
选项与隐藏试题,是说根据选项的内容来决定后面会出现什么题。
举个例子,如果一个是男的,一个是女的,后面题可能不一样。
一个是青年一个是老年,后面题也可能不一样。


5.问题类型那边删、改操作的策略是怎样的?


2016/05/27更新

1.关于为什么不采用一个问卷的试题是独立存储的原因?

我的leader给了我2点原因

(1)为了实现题库的复用

(2)为了能够实现统一的修改,以免造成修改上的麻烦

但是采用关联的办法其实是有很多坑的,始终有一个矛盾存在,想要复用试题与需要对试题独立修改的问题。

一旦有一个东西被复用,对于这个东西的修改(编辑、删除、新增一些附属物)都会影响引用了这个东西的实体。

当希望统一修改的时候,这是好的。当不希望统一修改的时候,这就是不好的。

其实对于leader的2点原因,我现在还是不赞成的。

(1)对于题库的复用,最终的目的是给用户有复用的体验而不是说一定要在后台数据库复用。

只要用户能够导入已经有的试题,对用户来说,就是复用了试题,并且可以随意修改自身的试题,带来了很大的灵活性。

(2)需要实现的统一修改。

确实这个问卷模块可能有很多很多份问卷,但是,具有相同的题目的问卷有多少呢?

可能有若干个,肯定不会有太多,所以完全没有必要为了方便修改而去挖一个维护上面的大坑。

当然,这是我目前的想法,采用了试卷对于试题是大家引用的,我去实现了,有坑。

但是对于我的想法,问卷独立持有问题的拷贝,我没有实际去实现过,也许也有坑也说不定,有时间实现一下就知道鸟。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值