45

我现在正在开发一个相当简单的调查系统。数据库模式将很简单:一个Survey表,与Question表处于一对多关系,与Answer表和与PossibleAnswers表处于一对多关系。

最近,客户意识到她希望能够仅向对之前的问题给出特定答案的人显示某些问题(例如,你买香烟吗?后面会跟着你最喜欢的香烟品牌是什么?,没有必要再问第二个)向非吸烟者提问)。

现在我开始想知道根据我的数据库模式实现这个条件问题的最佳方法是什么?如果question A有 2 个可能的答案:A 和 B,并且只有在答案是?question B时才应该向用户显示?A

编辑:我正在寻找一种将有关需求的信息存储在数据库中的方法。数据的处理可能会在应用程序端完成,因为我的 SQL 技能很烂;)

4

4 回答 4

131

调查数据库设计

最后更新:2015 年 5 月 3 日
图表和 SQL 文件现已在https://github.com/durrantm/survey提供

在此处输入图像描述

如果您使用此(顶部)答案或任何元素,请添加有关改进的反馈!!!

这是一部真正的经典,由成千上万人完成。他们总是看起来“相当简单”,但实际上它非常复杂。要在 Rails 中执行此操作,我将使用附图中显示的模型。我敢肯定,这对某些人来说似乎过于复杂,但是一旦你构建了其中的一些,多年来,你就会意识到大多数设计决策都是非常经典的模式,最好通过动态灵活的数据结构来解决一开始。
更多详情如下:

关键表的表详细信息

答案

答案表至关重要,因为它捕获了用户的实际响应。您会注意到 answer 链接到question_options,而不是questions。这是故意的。

输入类型

input_types是问题的类型。每个问题只能是 1 种类型,例如所有无线电拨号、所有文本字段等。当有(例如)5 个无线电拨号和 1 个“包括?”复选框时使用附加问题。选项或一些这样的组合。将用户视图中的两个问题标记为一个,但内部有两个问题,一个用于无线电拨号,一个用于复选框。在这种情况下,复选框将包含一组 1。

选项组

option_groupsoption_choices可让您构建“通用”组。例如,在房地产应用程序中,可能会出现“房产有多旧?”的问题。答案可能在以下范围内:1-5 6-10 10-25 25-100 100+

然后,例如,如果有关于相邻财产年龄的问题,那么调查将希望“重用”上述范围,以便使用相同的 option_group 和 options。

units_of_measure

units_of_measure就像听起来一样。无论是英寸、杯子、像素、砖块还是其他任何东西,您都可以在这里定义一次。

仅供参考:虽然本质上是通用的,但可以在此基础上创建应用程序,并且此模式非常适合Ruby On Rails框架,其中每个表的主键都具有诸如“id”之类的约定。此外,这些关系都是简单的 one_to_many,不需要 many_to_many 或 has_many throughs。我可能会添加 has_many :throughs 和/或 :delegates ,以便在没有.multiple.chaining 的情况下轻松地从单个答案中获取survey_name 之类的内容。

于 2011-05-02T14:53:42.553 回答
13

您还可以考虑复杂的规则,并在您的问题表中有一个基于字符串的条件字段,接受/解析其中任何一个:

  • A(1)=3
  • ( (A(1)=3) 和 (A(2)=4) )
  • A(3)>2
  • (A(3)=1) 和 (A(17)!=2) 和 C(1)

其中 A(x)=y 表示“问题 x 的答案是 y”,C(x) 表示问题 x 的条件(默认为真)...

这些问题有一个顺序字段,您将一个一个地检查它们,跳过条件为 FALSE 的问题。

这应该允许您进行任何复杂性的调查,您的 GUI 可以在“简单模式”下自动创建这些调查,并允许用户可以直接输入方程式的“高级模式”。

于 2009-02-14T00:35:36.210 回答
9

一种方法是添加带有字段的表“问题要求”:

  • question_id(链接到“哪个品牌?”问题)
  • required_question_id(链接到“你吸烟吗?”问题)
  • required_answer_id(指向“是”答案的链接)

在应用程序中,您在提出某个问题之前检查此表。使用单独的表格,很容易添加所需的答案(为“有时”答案添加另一行等......)

于 2009-02-12T11:29:13.597 回答
5

就个人而言,在这种情况下,我会使用您描述的结构并将数据库用作哑存储机制。我喜欢将这些复杂且依赖的约束放入应用程序层。

我认为在不为每个问题与他人的外键构建新表的情况下强制执行这些约束的唯一方法是使用 T-SQL 的东西或其他供应商特定的机制来构建数据库触发器来强制执行这些约束。

在应用程序级别,您有更多的可能性,并且更容易移植,所以我更喜欢这个选项。

我希望这将帮助您为您的应用找到策略。

于 2009-02-12T11:36:12.910 回答