用于调查的SQL设计,具有不同数据类型的答案

时间:2009-11-19 16:11:24

标签: mysql sql rdbms rdbms-agnostic

我正在进行在线调查。大多数问题的答案都是1-5。如果我们需要在调查中添加一个问题,我会使用一个简单的Web表单,将INSERT插入到相应的表中,瞧!调查正在提出新问题 - 没有新代码或更改数据库结构。

我们被要求添加可以获得不同数据类型答案的调查问题。规范是让调查“可配置”,以便在未来的任何时候,当有人说“我们需要一个新的调查,询问{text answer question},{1-5 question},{true false question} ,{带有日期作为答案的问题}“,我们可以在不改变数据库结构的情况下做到这一点。

我正在考虑存储这些答案的最佳方法,但我提出的每种方法似乎都有点hackish。

有些问题可能有一个是/否或真/假答案,有些问题可能有一个整数答案(“过去一个月有多少次你使用技术支持?”),另一个答案可能有一个日期,一个字符串,具有单个值的多项选择,具有多个值的多项选择等。或者,有时,特定答案值可能会提示子问题(“令您失望的是什么......?”)

简单的解决方案是将每个问题作为调查中的一个列,将其答案作为调查中的一列,以及是否将其作为调查中的一列。这对我来说感觉很乱 - 这是一张大餐桌;不是很“关系”。

头脑风暴,我能提出的“最佳”方法是为每种答案类型设置一个不同的表格,但这样会容易受到数据完整性问题的影响。换句话说,我会

CREATE TABLE `Questions` (...);
CREATE TABLE `TrueFalseAnswers` (...);
ALTER TABLE `TrueFalseAnswers`
  ADD CONSTRAINT `TrueFalseAnswers_ibfk_1` FOREIGN KEY (`question_id`)
REFERENCES `Questions` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
CREATE TABLE `TextAnswers` (...);
ALTER TABLE `TextAnswers`
  ADD CONSTRAINT `TextAnswers_ibfk_1` FOREIGN KEY (`question_id`)
REFERENCES `Questions` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

上述问题之一是我无法保证仅DDL中的任何问题都至少存在一个且只有一个答案。

另一个解决方案可能是在Questions表中为答案设置二进制或字符串列,并将所有答案编码为某种字符串或二进制格式,并将它们存储在答案列中。这为每个问题提供了至少一个且只有一个答案,但后来我无法访问SQL查询中的聚合功能。这让我觉得不是一个非常“关系”的解决方案。

所以,我发现上述想法存在问题。有没有“最好的”方法来解决这个问题?

现在我已经花时间来表达问题和我的想法,似乎我提出的广泛问题是“我想存储任意类型的数据而不进行任何编码...... “这是绝望的吗?

我正在使用MySQL,因此我无法访问其他RDBMS可能的内容。

4 个答案:

答案 0 :(得分:7)

使用指定答案类型的列,但将答案存储为文本。您的应用程序或前端可以使用answer_type列来确定向最终用户显示的内容(测试框,单选按钮,日期选择器)以及如何在将其发送回数据库之前对其进行验证。

答案 1 :(得分:2)

您想要创建一个与QuestionType类对应的QuestionType表。允许用户填写的持久答案为自由格式文本,并将其留待问题类型以确定答案的含义。

所以如果它是真/假,答案可能是'T'或'F'。

如果是多项选择,则答案可以是所选选项的索引。

如果是用户填写的文本框,请保存他们输入的文本。

答案 2 :(得分:2)

  我正在冒充的是“我想在不做任何编码的情况下存储任意类型的数据......”这是绝望的吗?

是的,它几乎就是。你提出的问题没有“好”的解决办法。最好的是Dave Swersky和Larry Lustig所描述的:

问题表,存储问题,可能的答案(如果是多项选择)和问题类型

答案表,存储问题的答案(FK到问题表),序列化为文本。除非绝对必要,否则Varchar(4000)或TEXT数据类型,最好是前者。

由应用程序逻辑决定根据为问题指定的类型确定值的含义。

答案 3 :(得分:0)

您也可以使用dataType指定的表,因此需要一个整数,日期,字符串等表。 从那里,1表的答案,将问题(表)链接到正确的dataType表+主键。

要对所有问题的答案进行概述,您可以在其上创建一个视图,只需将所有dataType转换为视图中的文本。