|
|
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
Всем доброго времени суток! Я проектирую базу данных для системы, предназначеной для тестирования пользователей. Одним из видов информации, хранимой в базе, являются вопросы которые могут быть разных типов: - Один или многие из многих (в таких вопросах пользователь должен отметить правильные ответы); - Самостоятельный ответ (пользователь должен самостоятельно набрать на клавиатуре текстовый ответ); - Сопоставление (пользователь должен соотнести ответы правильным группам) Мне нужно реализовать только первые два типа вопросов, а то что я сделал выглядит примерно так: Таблица для хранения вопроса Questions Код: plaintext 1. 2. 3. Таблица для хранения ответов на вопросы «Один или многие из многих» StandartAnswers Код: plaintext 1. 2. 3. Таблица для хранения ответов на вопросы «Самостоятельный ответ» FreeTextAnswer Код: plaintext 1. 2. Вопросы типа «Сопоставление» можно хранить в таких таблицах AnswersGroups Код: plaintext 1. 2. StandartAnswers Код: plaintext 1. 2. 3. Как можно организовать структуру, чтобы для одной записи таблицы Questions можно было бы привязать множество ответов только одного определенного типа? И как можно было бы позже внести поддержку для вопросов «Сопоставление»? Другими словами, если это нужно было бы сделать на C# то можно было бы создать базовый абстрактный класс вопроса, а затем, наследовавшись от него создавать нужные классы вопросов, а как можно поступить с БД ума не приложу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2011, 02:34 |
|
||
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
У меня получилось реализовать такую штуку на 5 таблицах. Плюс еще сколько-то для хранения списка классов, учеников по классам, результатов прохождения тестов и прочей обвязки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2011, 08:21 |
|
||
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
Основная таблица, на которой держатся варианты ответов: iQuestionItemIDiQuestionIDiQuestionItemNomersQuestionItemTextiQuestionItemIntValuesQuestionItemStrValue5 1 3 Intel 8086 0 6 1 1 Motorola 60000 0 7 1 5 Z-80 0 8 2 2 Голубая фишка 0 9 2 3 Голубой гигант -1 10 2 1 Голубой щенок 0 15 2 4 Голубая луна 0 16 1 2 Motorola 60010 0 17 3 1 Введите целое число равное числу байт. 0 818 6 1 Первый 0 IBM PC19 6 2 Второй 0 IBM PC XT20 6 3 Третий 0 IBM PC AT46 1 4 Intel 8088 -1 47 15 1 Даст ист фантастишь -1 48 15 2 Цигель цигель ай-лю-лю -1 В зависимости от типа вопроса форма, в которой пользователь заполняет ответы, приобретает нужный вид. При выводе вариантов выбора или полей для ввода значений используются поля iQuestionItemNomer, sQuestionItemText, iQuestionItemIntValue, sQuestionItemStrValue. При выборе одного варианта все просто - выводится список с галками sQuestionItemText, надо отметит одну, где iQuestionItemIntValue=-1 (iQuestionItemID 8..15). Для списка с несколькиим выбранными значениями - то же самое, просто галок может быть несколько (iQuestionItemID 47..78). Для расположить ответы в правильном порядке тестируемый должен добиться расположения строк-кандидатов sQuestionItemStrValue в порядке, заданном iQuestionItemNomer, напротив подписей sQuestionItemText (iQuestionItemID 18..20). Правда все без наследования, без классов, пара экранов примитивного кода VBA в аксесе. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2011, 08:35 |
|
||
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
Где-то в форуме по аксесу выложен полный архив - и редактора вопросов и опрашивающей системы. Попробуйте поискать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2011, 08:36 |
|
||
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
Grizzly284 Один или многие из многих (в таких вопросах пользователь должен отметить правильные ответы); То есть ответом будет являтся битовая маска или одно значение как вырожденная битовая маска с одним значением. Не забудьте упомянуть про ограничение на максимальное количество вопросов 32 или 64 Grizzly284 Как можно организовать структуру, чтобы для одной записи таблицы Questions можно было бы привязать множество ответов только одного определенного типа?Поясните на примере что вы хотите ограничить. Например 1 имеем структуру 2 пользователь (админ правящий данные, баг в программе выдающий кривой запрос) пытается сделать что-то, 3 база данных выдает ошибку. Что я вижу в хрустальном шаре - правильных ответов на вопрос может быть несколько (например синонимы для самонабранных ответов), но все они должны быть одного типа. Вы боитесь что на вопрос могут быть ответы разных типов. Что вам мешает игнорировать ответы неправильных типов? Например добавив поле тип ответа и смотря только в нужной таблице. Плюс регулярная чистка ответов неправильных типов если они таки попали в систему. Grizzly284 И как можно было бы позже внести поддержку для вопросов «Сопоставление»? Опять же нужет пример, а то я не понимаю чем соотнести ответ группе отличается от выбора подходящей группы (групп) разобранной ранее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2011, 19:13 |
|
||
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
Программист-Любитель Спасибо за ответ. Что-то аналогичное мне приходило на ум. Но при такой структуре таблицы в ней находится много полей, которые используются не для всех типов вопросов. Так например столбец iQuestionItemNomer нужен только для вопросов «Сопоставление» для остальных типов вопросов он не существенен; iQuestionItemIntValue – для вопросов «Один / многие из многих»; столбец sQuestionItemStrValue используется только в вопросах «Сопоставление» и «Произвольный ответ» в остальных же случаях он вообще пуст. И к тому же при желании внести в БД новый тип вопросов, например, пользователю нужно разместить ответы по определенным ячейкам таблицы, придется переделать всю структуру таблицы, избыточность в ней только возрастет и плюс к тому придется переделывать большую часть программы, которая работает с БД. Спасибо за ссылку рабочую программу, попробую найти. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2011, 21:03 |
|
||
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
SERG1257 > То есть ответом будет являться битовая маска или одно значение как вырожденная битовая маска с одним значением. Не забудьте упомянуть про ограничение на максимальное количество вопросов 32 или 64 Можно сделать и так. Я планировал сделать это через поле типа byt > Опять же нужен пример, а то я не понимаю чем соотнести ответ группе отличается от выбора подходящей группы (групп) разобранной ранее. Пример вопроса типа «Сопоставление» Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. > Поясните на примере что вы хотите ограничить . . . То как я планировал сделать БД было сделать: - Отдельно таблицу вопросов - Отдельно таблицы ответов к вопросам (отдельная таблица на каждый тип ответа) - Затем связывать ответы с определенной таблицы с вопросом Ограничение состоит в том чтобы если с вопросом уже связан хоть один ответ определенного типа (скажем, из таблицы AnswerTypeA ) то и другие ответы должны быть такого же типа (из той же таблицы AnswerTypeA ) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2011, 21:07 |
|
||
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
Grizzly284, пустые столбцы - не та проблема, о которой надо волноваться (если их не десятки конечно), они совершенно спокойно делаются NULL и никому не мешают. Еще и проверки можно повесить, какие столбцы для каких типов должны быть определены. Битовые маски можно хранить в полях типа varbinary, если возможно хранение более чем 64 вариантов. Хотя если вопросов с ответом да/нет много, то введение однобитового поля может съэкономить объем. Введение дополнительных типов вопросов может осуществляться добавлением nullable-полей, а может реализацией классического наследования. Или например добавления поля xml. Короче вариантов масса. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2011, 21:15 |
|
||
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
iljyGrizzly284, пустые столбцы - не та проблема, о которой надо волноваться (если их не десятки конечно), они совершенно спокойно делаются NULL и никому не мешают. Еще и проверки можно повесить, какие столбцы для каких типов должны быть определены. Битовые маски можно хранить в полях типа varbinary, если возможно хранение более чем 64 вариантов. Хотя если вопросов с ответом да/нет много, то введение однобитового поля может съэкономить объем. Введение дополнительных типов вопросов может осуществляться добавлением nullable-полей, а может реализацией классического наследования. Или например добавления поля xml. Короче вариантов масса. Простите что не уточнил работаю с MS SQL Server, а эта СУБД не является объектно ориентированой и соответственно наследование в ней не возможно. Или я что-то не так понял? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2011, 22:01 |
|
||
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
Хоть идея и бредовая но мне сначала казалось что можно сделать как на прикрепленном рисунке Можно поставить ограничение IdQuestionType = IdAnswerType Но следующие ограничения поставить нельзя: IdQuestion и IdQuestionType из одной и той же таблицы Question IdAnswer и IdAnswerType из одной и той же таблицы AnswerTypeXXX Поле IdQuestionType должно быть одинаковым для всех записей с одним и тем же значением IdQuestion ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2011, 22:06 |
|
||
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
Grizzly284, наследование возможно в любой СУБД. Реализуется довольно банально: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Код: plaintext 1. 2. 3. 4. 5. Аттрибуты, относящиеся к базовому классу, хранятся в таблице T_A, аттрибуты класса-потомка - в таблице T_B. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2011, 22:27 |
|
||
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
авторМожно сделать и так. Я планировал сделать это через поле типа bytЭто как, как список в строчку isAnsw1, isAnsw2, isAnsw3, isAnsw4 ... или в столбик orderNo, isSet IMHO битовая маска это то что доктор прописал. Вопрос с более 64 вариантов мне трудно представить (очень неудобно на экране для людей), но это надо явно оговорить. авторПример вопроса типа «Сопоставление»То есть ответ у вас неатомарный create table answersGroup (id int, quest_id int, group_id int, answ_bitmask bigint) авторОграничение состоит в том чтобы если с вопросом уже связан хоть один ответ определенного типаОпять же не вижу проблемы. Имеем create table questions (quest_id int, quest_type int ....) craete table anwsersText (id int, quest_id int, answ_text varchar(100)) craete table anwsersInt (id int, quest_id int, answ_int bigint) create table answersGroup (id int, quest_id int, group_id int, answ_bitmask bigint) В любой из них на каждый вопрос может быть более одного ответа Далее пусть у нас имеется ответ в каждой таблице. Кому от этого хуже? При сравнении ответа пользователя с эталонным джойн будет согласно quest_type и лишние ответы просто не будут учитываться. Пользователь добавляет ответы с помощью программы и стало быть не имеет возможности всунуть ответ в левую таблицу. Всунуть ответ в левую таблицу может только админ или баг. Тогда пусть по ночам будет выполнятся запрос для каждого типа select * from questions q where quest_type=1 and (exists (select * from anwsersInt q where q.quest_id = a.quest_id ) or (exists (select * from answersGroup q where q.quest_id = a.quest_id ) ) на случай возможных ошибок. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.10.2011, 23:28 |
|
||
|
Трудности с проектированием (БД для хранения тестов)
|
|||
|---|---|---|---|
|
#18+
iljy, спасибо за совет. Вот моя реализация. Это то что вы имели в виду? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.10.2011, 00:17 |
|
||
|
|

start [/forum/topic.php?fid=32&msg=37485687&tid=1541981]: |
0ms |
get settings: |
9ms |
get forum list: |
19ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
192ms |
get topic data: |
12ms |
get forum data: |
2ms |
get page messages: |
71ms |
get tp. blocked users: |
1ms |
| others: | 237ms |
| total: | 551ms |

| 0 / 0 |
