即使我使用Django的ORM来实现这些表,我也故意将其作为一般性问题进行构建。 Here are my Django models如果你想看一眼。
我有几个表有以下关系:
Survey <--m2o-- Page <--m2o-- Category <--m2o-- Question <--m2o-- Choice <--?-- Response
| | | | |
|- name |-number |- name |- sortid |- sortid
|- sortid |- text |- text
|- text |- short
|- qtype
m2o
是多对一的简写,每个表都有一个隐含的主键,我的问题是关于如何组织响应表。
响应表应该与User表有某种关系(取决于表定义,这可能是一对一或多对一)。该表的目的是存储用户对特定问题的回答。我遇到的问题是,根据问题类型,我需要在Response表中将响应存储在不同的列类型中。例如,表可能类似于:
| user | (question) | (qtype) | choice | response |
|------+------------+-----------------+-----------+-------------------------------|
| 1 | Q1 | Select One | A | False |
| 1 | '' | '' | B | False |
| 1 | '' | '' | C | True |
| 1 | .. | '' | D | False |
| 1 | Q2 | Select Multiple | 1 | True |
| '' | '' | '' | 2 | True |
| '' | '' | '' | 3 | False |
| '' | '' | '' | 4 | True |
| '' | Q3 | Long Text | NULL | "It was the best of times..." |
| '' | Q4 | Select Explain | A | False |
| '' | '' | '' | B | False |
| '' | '' | '' | C | False |
| '' | '' | '' | D (other) | True |
| '' | '' | '' | Explain | "I actually prefer bananas." |
为了清晰起见,我添加了列,这些列将由关系隐式定义,因此不会出现在实际表中。它们用( )
表示。此外,choice
实际上是外键。
似乎响应列可能需要是文本列。将其分成两列或更多列,例如response-text
和response-boolean
会让人觉得麻烦。我们可以轻松地为单个用户提供数百行。
我还想过组织这样的表:
| user | survey | response (key-value store) |
|------+--------+--------------------------------------------|
| 1 | 1 | {"q1": "C", "q2": "1,2,4" |
| | | "q3": "It was the best of times..." |
| | | "q4": "Other: I actually prefer bananas."} |
| 2 | 1 | {...} |
| 3 | 1 | {...} |
如果你在什么情况下解释你的定义不会很好的话,可以给予奖励。
如果你想想象我的情况,这里有一些关于我背景的笔记:
我怀疑我的情况接近N1NF on Wikipedia的例子。
我刚刚听说过多表继承或多态,我不知道如何将它应用于这个问题。具体来说,我不确定哪些表会从继承中受益。例如,Response应该扩展选择吗? Page扩展调查吗?
答案 0 :(得分:4)
我是首席架构师&amp; http://360test.nl/的开发人员使用调查来衡量团队绩效等。
我们的基本表格结构与您的不同。
回答存储在一个相当简单的表格中:
ID | Participation | Question | RawValue
Participation
是一个用户参与一项调查的ID。 Question
是调查中一个问题的ID。 RawValue存储一个答案。它的格式取决于问题类型。对于更复杂的json构造,它可以是单个数字(对于简单的“选择一个”问题)(例如,对于“在Y选项上分配X点”类型的问题)。问题类型知道如何序列化/反序列化数据可用的东西。
我们不在表格中使用继承。如果我们需要调查答案的在线查询(“调查xyz中有多少用户选择答案3”),这是有道理的,但我们不需要这样做。因此,我们可以使用我们简单的“通用”RawValue列。当我们显示调查结果时,将加载所有答案,对其值进行反序列化并根据问题类型进行评估。 如果我们需要更多特殊报告,我们会离线生成它们并将结果存储在某处。
我认为,即使您建议的方法(将所有答案都存储在一列中)也可以为我们工作,因为我们无论如何都会在执行评估时加载整个数据。
我并不是说我们的方法是最好的,但它对我们有用。
总的来说 - 规范化是一个重要的话题。但这并不意味着,一切都需要规范化。虽然我将核心域模型的持久表示归一化,但我有时会在数据库中存储严重非规范化的数据,以便从域模型生成报告。您知道它是非规范化的以及数据的来源非常重要。
我使用我认为CQRS架构编写软件,我学到的一件事是非规范化可能是一件非常好的事情。一些CQRS专家建议每个网页使用一个表,其中包含该页面所需的所有(非规范化)数据。虽然这不一定是您应该始终做的事情,但它表明在所有情况下都不需要教科书规范化。