I am designing a simple database of online exam system. But I can not figure out how the questions and the answers should be stored. I am thinking question and Answer as different entities. There will be both MCQ and short questions in the same question set and the number of questions in a set may be dynamic (choose by teacher).
As I see you're looking for something like this:
User table - everyone who will be answering to the questions. It will have UserId and other profile information - name, class, photo, etc.
Question table - it will have questionid, created by (userid) and text of the question
AnswerOption - it will have optionid, link to question, text of answer option
UserAnswer - it will have useranswerid, questionid, optionid
So for example you have this question: "How much is 2*2?" and answer options are "4", "5", "6".
In this case you will have 1 record in question table and 3 records in AnswerOption table.
Now when someone answers the question, you insert a record into UserAnswer table with respective userid, questionid and optionid.
Is this what you had been looking for?
And of course you should also think how to group questions in test etc.
Since you've got multi-choice questions (MCQ, I assume), you need to consider carefully whether the alternatives in an MCQ are part of the question or are answers with a status (wrong, part of the right answer, correct). If a question has multiple answers, keep them in separate tables. If a question has just one answer, then keep them in a single table.
Start from your smallest item. A question can have multiple answer choices, one of which is good. So you could have an answer table.
ANSWER:
AnswerID
QuestionID
Choice
Text
Good (boolean qualifier)
QUESTION:
QuestionID
Text
Points
This is just a suggestion. It all depends on what you want to do. But first, you lay out by categories what your items are. Prefer loose leaf paper.
Related
I'm building a simple let's say survey app. I have the following requirements:
User:
- name
- surname
- age
Question:
- question (text)
- type
- author
Answer:
- value
- date
I want users to give questions to answers and I want to be able to query the following:
Get user's questions and answers
Get question and its answers
Get user's questions and answers by (or where) type
Get answers to questions by value (or where value)
Count answers to a question
Get answers to a question by user age
Get answers to questions over time (by user or general)
So far I came up with the following solution:
So here the Partition Key is the ID and the Sort Key is type
So the first problem is the first requirement:
Get user's questions and answers
Shall I add another type which would be user ?
Now how to:
get a question and its answers ?
I can query id = 1 and type starts with question but then I can get a lot of unnecessary user records.
Now the next one:
get user's answers to questions of specific type (type as question attribute)
How to count same answers to a question?
I'm new to DynamoDB so any help is greatly appreciated!
I would add an id (uuid generated from code) for each table.
Get user's questions and answers
Set userId as field in both Question and Answer, then set an index on that. This will allow you (with 2 separate queries) to get all questions and answer of a particular user.
get a question and its answers ?
Answer will have as field questionId and same index principle applies
get user's answers to questions of specific type (type as question attribute)
You can add a field to Answer, which is questionType and filter on that. Remember that NoSQL schema focuses on the queries you need, not for a perfect normalised schema.
How to count same answers to a question?
I am guessing you meant how many answers does a question have. Well if you know the questionId, just follow "get a question and its answers ?" and execute a .withSelect(Select.COUNT) on the query
EDIT
User:
- userId (hash key)
- name
- surname
- age
Question:
- questionId (hash key)
- question (text)
- type
- author
- askedByUserId (index - hash key)
Answer:
- answerId (hash key)
- value
- date
- answeredByUserId (index - hash key)
- questionId (index - hash key)
So everything depends on how you query data (and of course you may end up switching to SQL even, noSQL not an 1:1 replacement). Referring just by id is not wrong, I would prefer to have immutable questions and answers instead of editing a question every time it receives an answer. So take into consideration that you can't use joins and always prefer immutable data (add a new value instead of editing).
EDIT 2
In order to get all questions and answers from a User, create and manage this table:
UserItems:
- userId (hash key)
- question (full json of a question, optional)
- answer (full json of a answer, optional)
So every time you create a new question for example, add it to both Question and UserItems. Do a simple query based on hash key and you will get all questions and answers, with full data. Again, this is based on your querying needs.
Ok, so it took me a few good hours to figure out the answer.
Let's start with the entities and their relationships, here is the diagram:
Where:
USR - User
ANS - Answer
QUE - Question
As it can be seen above, I don't have any many-to-many relationships so the only pattern I will be using for retrieving the data is the Primary Key (Partition Key + Selection Key) pattern.
If I had many-to-many relationship in the model, apart from PK+SK I would also use GSI (Global Secondary Index)
GSI can also be used to create a different view, for example by swapping places of PK with SK.
Now the DB access patterns:
The above unfortunately doesn't cover all the access patterns, a few more I can think of are:
Query answers by user age
Query answers to a question and calculate percentage of answers by type (should this be calculated outside of the DynamoDB?)
And now the DB Table design:
So based on the access patterns in the Access Patterns table with this design I can query:
All the answers of a user to a question
SELECT PK=USR_1 WHERE SK begins_with(AR_QUE_2)
All the answers to all the question by a user
SELECT PK=USR_1 WHERE SK begins_with(AR_QUE) - in this case I would have to include question metadata (question itself as text) in the attributes of the AR_QUE_X_ANS_Y so that I don't have to query the table multiple times to get all the questions metadata.
All the answers to a question
Select PK=QUE_2
I'd really love to hear someone's opinion on this one.
I also appreciate that in some cases I would have to denormalise data and insert metadata information in Attributes.
I am still very curious how I could calculate number of answers by type to a question and calculate for example a percentage of answers of different type.
My data consists of questions and answers. It also shows what the versionNr is of the answer and shows which persons changed which Answer. Its possible that some questions have the same answer.
questionID Question Answer VersionNr User date
1 Who is....? W.H. Smith 1.0 ...#test.com 1/1/14
1.1 ...#test.com 3/8/14
2 What is...? 3% 1.0 ...#test.com 1/2/14
RG = Repeating Group
Bold = Composite/Primary Key
0NF:
(questionID, question, AnswerID, answer,RG{versionNr, user, date}
1NF:
(questionID, question, AnswerID, answer)
(questionID, AnswerID, VersionNr, user, date)
2NF/3NF:
Q(questionID, question, AnswerID)
Ans(AnswerID, answer)
Version(questionID, AnswerID, VersionNr, user, date)
My question is whether I should remove questionID from Version, because the versionNr, date and User gives information about the Answer and Not the question.
If there can be many version records for one answer record, then yes, QuestionID should not be in Version, as it is redundant data: You can always tell the QuestionID of a Version by looking up the Answer record.
That said, it's not clear to me what you're trying to model. When you say that a user can change an answer, do you mean that this is a quiz and users can change what the "right answer" is? Or do you mean that they can change the answer they gave to a quiz or survey?
But if there are many Version records for one Answer, than you are not recording what the answer was at each step, you are just recording who made the change. Maybe that's all you need to know for your purposes. But if the idea is that you want to record what the answer was for each version, then Answer and Version should be a combined into a single table. In that case you need questionID in the Answer/Version record because otherwise you have no way to know which question any answer other than the latest is for.
If the idea is that there is just one Answer record for each Question, and then many versions, then Question and Answer should be combined into a single record. Well, you say that several questions can share the same answer. As I asked in a comment, what does this mean? Are you talking about answers that are the same by coincidence, like on question is "How much is 2+2?" and another is "What is the square root of 16?" and both answers happen to be 4? Or do you mean that they are really the same answer in the sense that if the answer to one question changed, the answer to the other would logically and inevitably have to change to the same thing? Like, "Who is the current vice president of the United States?" and "If the president of the United States died, who would become president?"
I'd think the logical schema would be this:
Question (questionID, question_text)
Answer (answerID, questionID, version_number, answer_text, user, change_date)
Then the current answer is
select answer_text
from answer
where questionID=#qid
and version_number=(select max(version_number) from answer
where questionID=#qid)
This requires no redundant data.
An obvious denormalization for performance and simplicity would be to put the answerID of the current answer in the Question record.
If I understand your problem correctly, I believe you can do the following to achieve a working 3NF schema.
Q(questionID, question)
Ans(AnswerID,answer,QuestionID)
Version(VersionNr,AnswerID,User,date)
(Italics are foreign keys)
So, the primary key of version is triple {VersionNr,AnswerID,User). Please explain if something is not correct with my solution.
So, to sum up, no, you don't need to have questionID inside version, since you can find it with joins.
UPDATE
I think I understand your problem and I believe the correct solution is the following.
Q(questionID,question)
Ans(AnswerID,answer)
Version(QuestionID,AnswerID,VersionNr,user,date)
Actually, your relationship between answers and question is many to many, since many answers are connected to many questions. So, you can use Version as the intermediate table to construct this many to many relationship.
Additionally, you can add the version number, the user and the date in that intermediate table, to have all the necessary information.
I have read through a lot of the threads here and have found a good amount of useful input...but there are a couple of questions that remain unanswered.
I am storing questions & answers from a questionnaire in a database.
I have the tables:
Survey (surveyID)
Question (questionID, surveyID, questionType, Question)
Answer (answerID, userID, questionID, answer)
User (userID, username)
Question 1: multi-value questions...I would have a separate row for each value in the answer table....but have the same questionID and userID. But then how would you work the following:
-what are your coping strategies (multi-value)
-how frequently do you use each coping strategy?
i.e. a one-one relationship of coping strategy-frequency.
The solution above (i.e. one row per answer doesn't work because you need the relation between the specific coping strategy and the frequency).
A similar question is for the following:
have you been involved in conflicts over land-use rights?
with whom? (multi-value)
for what reasons?
(i.e. what were your reasons for conflict with the neighbours, what were your reasons for conflict with the authorities?) ...i.e. one to many on a multi-value attribute
Thank you in advance, I hope I have explained my query sufficiently well.
Becky
I need to store in a DB (MSSQL) multiple answer questions, and I am having trouble deciding what is the best way to do so. Should I store questions in one table, all answers in another and right answers in a 3rd table? Should they all be in the same table?
I would love to hear your ideas
thanks
Amit
Each concept, or entity, should be in its own table.
Questions in a Question table
Answers in an Answer Table with a QuestionID with a boolean field indicating its right or wrongness
(unless Answers can belong to more than one question?)
To me in your case best way is to hold question and answer in seperate tables. If your question has multiple answer and you maybe want to use one answer in a lot of question its the best way. You should also add table for which answer is good for specific question.
In this way you don't have data redundancy in database.
I agree with podiluska.
Each entity in a table.
If all or any of answer can be "typified" (i.e. not "free answer"), add a table for "typified answers" relating this one with table questions (to prevent someone to choose inapplicable "typified answers".
In table "user answers" relate it with table "questions" and if some record (or answer) contains a not "typified" you can mark it with a boolean column indicating "right" or "wrong".
I hope have helped you.
Wondering what is the best way to model out a questionnaire in terms of saving the response. So I would assume the ideal way to save it would be a table like this:
ID_pk
response_id
question_id
value
So each entry would be an answer to a question. The question is when I search on this table the performance would be bad. I was wondering do I need to create another table on the side to help me with performance. Any ideas?
Thanks
The best approach depends on how flexible you need this to be. Will you have multiple choice questions? Numeric-only questinos used for calculaitons? True/False questions, etc.
The approach that worked for us to enable ultimate flexibility has this structure:
Table: Surveys
SurveyId PK
Surveyname
Table QuestionTypes
QuestionType PK
QuestionTypeText (ie "Multiple Choice", "True/False", etc.)
Table Questions
SurveyId FK
QuestionId PK
QuestionText
QuestionType
Table Answers (Contains answers ONLY for multiple choice questions)
Answerid PK
QuestionId FK
AnswerText
Table Results
ResultId PK
Surveyid FK
QuestionId FK
QuestionType (copied in from Question)
MultipleChoiceAnswerid (null unless it was a multiple choce question, FK to Answer otherwise)
BooleanResult (if QT = boolean, null otherwise)
NumericResult
FreeFormTextResult
and then a lot of programming logic to handle the display.
Actually, our real soultion goes a stp further and groups questions into QuestionGroups so that similar questions can be kept together, but this simplified version should give you some ideas. It's relatively complex, but I've seen professional survey software that's even more so, but follows a similar pattern. it's also worked out very well for us. We've been able to reuse it for several scenarios by creating a new SurveyType.
The idea is that anything that can be duplicated in a table should be pulled out to another table.
Question would be duplicated, so you'd need a questions table
Response could be duplicated, depends on if this would be multiple choice or fill in the blank, etc.
Value could be duplicated, but depends on the answer from Responses
So, I'd say to think about your questionnaire. Think about what would be saved multiple times in the db and then normalize from that.
Don't worry about performance - normalization will help more than it will hurt.