Нормализация базы данных: Как я могу табулировать данные? - PullRequest
2 голосов
/ 03 января 2012

Мой вопрос касается нормализации данных.

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 |
------------------------

В конечном счете, я хотел бы знать, сколько раз пользователь ошибался в определенном вопросе с течением времени.Кроме того, мне нужно отслеживать, из какого теста пришли неправильные вопросы.Это то же самое для рассмотренных вопросов.Кстати, в одном и том же случае вопросы могут быть рассмотрены и неправильны.

Я предложил 2 разных способа представления данных, но мне не нравится ни один из них.

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

ИЛИ

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

Примечание. Неправильная / проверенная категория считает, сколько раз число Q попадает в эту категорию.

МОИ ВОПРОСЫ ОБОБЩЕНЫ

Как эффективно представить неправильные / проверенные вопросы в таблице?Таблица 1 настроена эффективно?

РЕДАКТИРОВАТЬ: Вопросы, на которые были даны неправильные ответы, могут быть использованы для создания новых тестов.Только неправильные вопросы будут использоваться для тестов.Если сгенерированный тест пройден, проверенные вопросы будут помечены как проверенные.Оценка не будет обновлена, так как это будет новый тест, и будет создан новый test_id.

ПРИМЕЧАНИЕ -Возможно повторить старые тесты, но оценка не будет обновлена.Новый экземпляр будет создаваться для каждого пройденного теста.

Что касается сгенерированных тестов, я предполагаю, что это означает, что мне нужно будет включить еще одну таблицу, чтобы отслеживать, из какого теста были получены вопросы.Извините, я не думал об этом до самого конца.

СПАСИБО

Мне было трудно выбрать ответ, так как все дали мне действительно полезныйИнформация.Мой окончательный дизайн будет учитывать все, что вы сказали.Еще раз спасибо.

Ответы [ 4 ]

2 голосов
/ 03 января 2012

Пересматривая мой ответ после ваших обновлений, я придумал такую ​​компоновку, которая, я думаю, будет работать очень хорошо.

В качестве предварительного условия, я предполагаю, что у вас есть какие-то тесты и вопросы.Для согласованности я включил их (только с соответствующими столбцами) в свой макет.

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.

. При таком подходе вы получите полную историю того, сколькоВ случае, если до того, как он был успешно рассмотрен, была предпринята попытка ответить на вопрос, который не удалсяи моя предложенная модель ввела бы дублирование данных.Вы заметите, что я пропустил идентификатор ревизии из этой таблицы, потому что для тестового экземпляра (и любого количества ревизий) существует только одна оценка.

1 голос
/ 04 января 2012

Из приведенного выше примера я предполагаю, что экземпляр напрямую связан с комбинацией user_id + test_id. Если это так, вы можете рассмотреть вопрос о наличии таблицы 2 в следующем формате:

Экземпляр | вопрос_ид | статус | дата

PK для таблицы должен быть на instance, question_id и status.

записи в этой таблице не будут обновляться, только вставляются. Таким образом, вы можете иметь:

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

это позволит вам полностью отслеживать неправильные и проверенные вопросы, а также дату рассмотрения. если вам не нужна дата проверки, не определяйте этот столбец:)

Вы можете добавить уникальный индекс для полей экземпляра и статуса, поэтому при доступе к таблице ваш поиск будет более эффективным.

* Дополнительные данные, которые можно добавить во 2-ю таблицу, - это «новые test_id» и «новый вопрос_ид» для рассмотренных вопросов, так что вы можете проверить, не возникли ли сбои для одного и того же вопроса (при условии, что вопрос_ид создается каждый раз) .

1 голос
/ 03 января 2012

Говоря о нормализации и просто чтобы убедиться, что вы можете извлекать все виды рассчитанных данных из вашей базы данных, я бы предложил более сложную модель, которая в конечном итоге станет чем-то более простым в управлении ...

Вам понадобятся следующие таблицы

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 ...)

Возвращаясь к вашим потребностям, мы получаем следующее:

  • длительность рассчитывается с использованием startDate и endDate of instance_table
  • оценка рассчитывается как сумма истинных значений из поля questionResult
  • вы можете отслеживать и сравнивать ответы на один и тот же вопрос по времени для одного пользователя
  • Таким образом, ваши рассмотренные вопросы могут быть определены как вопросы с хотя бы одним ложным значением для конкретного пользователя
  • если ваша база данных поддерживает нулевые значения для логических полей, у вас будет возможность отслеживать оставшиеся без ответа вопросы (с questionResult = Null). В противном случае я советую вам использовать или создать поле из трех состояний (например, целое число с разрешенным нулем, плюс значения 0 и 1), чтобы следовать за неотвеченными вопросами (пусто), неправильными ответами (0) и правильными ответами (1).
  • Оценка, равная 100 * (количество хороших ответов) / (количество вопросов в тесте), может быть легко рассчитана с помощью SQL-агрегатов.
  • Вы даже можете рассчитать частичные оценки как количество хороших ответов / количество вопросов, на которые дан ответ в тесте.
  • Эта модель принимает любое количество тестов, любое количество вопросов на тест, любое количество экземпляров, любое количество пользователей ...
  • Конечно, его можно еще улучшить, добавив отсутствующие свойства в таблицы (например, поля testNumber, questionNumber)
  • и т.д ...
1 голос
/ 03 января 2012

Предполагая, что количество вопросов в тесте не меняется, и что каждый вопрос оценивается одинаковым количеством баллов, я предлагаю следующие таблицы:

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   |
------------------------------------
...