数据库规范化:如何将数据制成表格?

时间:2012-01-03 15:31:37

标签: mysql sql database normalization

我的问题是关于数据的规范化。

INFO

我正在尝试将数据库中的测试结果制成表格。我想记录的信息是test_instance,user_id,test_id,完成(日期/时间),持续时间(测试),得分,错误问题和已审核的问题。

在大多数情况下,我认为我会根据表1组织信息,但是我试图找出记录错误或已审查问题的最佳方法。请注意,我不要想要将所有不正确的问题放在一个条目中,如表2所示。

我想为每个错误标记的问题(或已审核的问题)单独输入一个条目。

注意:已审核的问题是指某个时间或某些问题被错误标记,因此需要再次进行测试。

表1

-------------------------------------------------------------   
|  instance   | user_id | test_id |completed |duration|score|   
-------------------------------------------------------------   
|      1      |   23    |   33    | 2JAN2012 |  20m   |  75 |   
|      2      |   11    |   12    | 10DEC2011|  35m   | 100 |   
|      3      |   1     |    3    | 3JUL2008 |  1m    |   0 |   
|      4      |   165   |   213   | 4SEP2010 |  10m   |  50 |   
------------------------------------------------------------- 

表2

------------------------
|  instance   ||wrong Q|
------------------------
|      1      || 3,5,7 |
------------------------

最后,我想知道一个用户多长时间遇到一个错误的特定问题。另外,我需要跟踪错误问题来自哪个测试。对于已审核的问题,这是相同的。 顺便提一下,在同一个实例中可能会对问题进行审核和错误。

我提出了两种不同的方式来表示数据,但我不喜欢它们中的任何一种。

------------------------------------------------- 
|  instance   | Q number |  Wrong  |  Reviewed  |
-------------------------------------------------

---------------------------------------------------
| user_id | test_id | Q number | Wrong | Reviewed |
---------------------------------------------------

注意:错误/已审核类别正在计算Q编号属于该类别的次数。

我的问题概述

如何在表格中有效地表示错误/已审核的问题?表1是否有效设置?

编辑:错误回答的问题可用于生成新测试。只有不正确的问题才会用于测试。如果进行了生成的测试,则测试的问题将被标记为已审核。分数不会更新,因为它将是一个新测试,将生成一个新的test_id。

注意 - 可以重新参加旧测试,但不会更新分数。将为每个测试创建一个新实例。

关于生成的测试,我想这意味着我需要再添加一个表来跟踪问题最初来自哪个测验。对不起 - 我一直没有想到最后。

感谢

我很难选择答案,因为每个人都给了我非常有用的信息。我的最终设计将考虑到你所说的一切。再次感谢。

4 个答案:

答案 0 :(得分:2)

在您更新后重新审视我的答案时,我想出了这种布局,我认为这种布局非常合适。

作为先决条件,我假设你在某处有测试和问题。为了保持一致性,我在我的布局中包含它们(只有相关的列)。

USERS
- user id

TESTS
- test id

QUESTIONS
- question id
- test id

然后是有趣的部分。考虑一下你的意思:

  

可以使用错误回答的问题进行生成   新的测试。只有不正确的问题才会用于测试

您没有提到可以重复测试的次数,我假设无限期或至少不止一次。

TEST INSTANCE
- instance id [PK]
- revision id [PK]
- user id
- completed
- duration

COMMENT: you may want to consider replacing completed and duration with 
a start and end timestamp. They will serve the same purpose without 
the need for any calculations at insert/update.

TEST INSTANCE SCORE
- instance id [FK, TEST INSTANCE (instance id)]
- score

FAILED QUESTIONS
- question id [FK, QUESTION (question id)]
- instance id [FK, TEST INSTANCE (instance id)]
- reviewed [FK, TEST INSTANCE (revision id)]

然后是我的评论。

正如我所看到的,对失败问题进行新的实际测试是没有意义的,所以我在revision id表中添加了TEST INSTANCE。每次重新测试时,都会创建具有instance id的相同revision id的新记录(例如,正在运行的数字序列)。

任何失败的问题都会与FAILED QUESTIONS一起存储在instance id中,NULL最初会存储reviewed。如果审核失败的问题,则reviewed列将使用revision id的最新测试实例的instance id进行更新。

使用这种方法,您将获得在成功审核之前尝试失败问题的次数的完整历史记录。

此外,我在修改后的答案中选择将分数移至自己的表中,因为您说尽管查看失败的问题并且我提出的模型会引入数据重复,但分数不会更新。您会注意到我从该表中遗漏了修订版ID,因为对于测试实例(以及任意数量的修订版),只有一个分数。

答案 1 :(得分:1)

假设测试中的问题数量没有变化,并且每个问题的价值都相同,我建议如下表格:

test
----
test_id
number_of_questions

test_instance
-------------
instance_id
user_id
test_id
completed
duration

notable_questions
-----------------
instance_id
question_id
status (W - Wrong, R - Reviewed)

所以,例如:

test:
---------------------------------
| test_id | number_of_questions |
---------------------------------
|     3   |         50          |
|    12   |        100          |
|    33   |         78          |
|   213   |         50          |
---------------------------------

test_instance:
-------------------------------------------------------
| instance_id | user_id | test_id |completed |duration|
-------------------------------------------------------
|      1      |   23    |   33    | 2JAN2012 |  20m   |
|      2      |   11    |   12    | 10DEC2011|  35m   |
|      3      |   1     |    3    | 3JUL2008 |  1m    |
|      4      |   23    |   213   | 4SEP2010 |  10m   |
-------------------------------------------------------

notable_questions:
------------------------------------
| instance_id |question_id| Status |
------------------------------------
|      1      |     3     |    W   |
|      1      |     5     |    W   |
|      1      |     7     |    W   |
|      4      |     2     |    R   |
------------------------------------

答案 2 :(得分:1)

谈到规范化,并且为了确保您可以从数据库中检索所有类型的计算数据,我会提出一个更复杂的模型,最终会有更容易管理的内容...

您需要以下表格

test_table
    PK: id_test
    testDescription

question_table
    PK: id_question
    FK: id_test
    questionDescription

instance_table *please note that duration and scores will be calculated later on
    PK: id_instance
    FK: id_user
    FK: id_test
    startingTime
    endingTime

question_instance_table
    PK: id_question_instance
    FK: id_instance
    FK: id_question
    questionResult (Boolean)
    (please note here that the PK could be id_instance + id_question ...)

回到您的需求,我们有以下内容:

  • 持续时间是使用instance_table
  • 的startingDate和endingDate计算的
  • 得分计算为来自questionResult字段的真值之和
  • 您可以针对一个用户跟踪和比较同一问题的答案
  • 因此,您查看的问题可以定义为特定用户至少有一个错误值的问题
  • 如果您的数据库支持布尔字段的空值,您将有可能遵循未回答的问题(使用questionResult = Null)。否则,我建议你使用或建立一个三态字段(允许空值的整数,例如加上0和1值)来跟踪未答复的问题(空),错误答案(0)和正确答案(1)。
  • 分数,即100 *(好答案的数量)/(测试中的问题数量),可以通过SQL agregates轻松计算。
  • 您甚至可以将部分分数计算为答案的数量/在测试中回答的问题数量。
  • 此模型接受任意数量的测试,每次测试任意数量的问题,任意数量的实例,任意数量的用户......
  • 当然,可以通过向表中添加缺少的属性来进一步改进(例如,testNumber,questionNumber字段)
  • 等...

答案 3 :(得分:1)

从上面的例子中我假设该实例直接与user_id + test_id组合相关。 如果是这样,您可以考虑使用以下格式的表2:

实例| question_id |状态|日期

表的PK应该是实例,问题和状态。

此表中的条目不会更新,只会插入。这样你就可以:

Instance | question_id | status | date
   1           3            W     1/1/2011
   1           3            R     1/5/2011

这将允许您完整跟踪错误和已审核的问题以及审核日期。如果您不需要审核日期,请不要定义此列:)

您可以在实例和状态字段中添加唯一索引,因此当您访问该表时,搜索效率会更高。

*可以添加到第二个表的其他数据是“new test_id”和“new question_id”用于已审核的问题,以便您可以检查是否存在相同的问题(假设每次都生成question_id)您仍然有失败