I'm making an online quiz with php and mysql and need a bit of help deciding how to design the database for optimal insert of questions/answers and to select questions for the quiz. The table will hold 80 questions each with 4 possible options plus the correct answer.
When retrieving the questions and options from the database I will randomly select 25 questions and their options.
Is it better to make a single column for all questions, options, and correct answers? For example:
ID | Q | OPT1 | OPT2 | OPT3 | OPT4 | ANS
Or would it be better to make a column for each individual question, option, and correct answer? For example:
Q1 | Q1_OPT1 | Q1_OPT2 | Q1_OPT3 | Q1_OPT5 | Q1_ANS | Q2 | Q2_OPT1 | Q2_OPT2...
It'd be better to store the possible answers in a seperate table. This allows you to have any amount of answers per question instead of just 4. It also allows questions to have a different number of answers. If you have more than one quiz, you may also want a Quizes Table.
Quizes:
id
name
Questions:
id
quiz
prompt
Answers:
id
question
prompt
QuizResult (someone taking a quiz)
id
quiz
// other information about the quiz taker, possibly including the time
Now the correct answer thing gets a lot more tricky. I prefer the higher implementations here:
Each question has a value and each answer has value
A system I recently worked with you could assign a point value for each question and each answer. Incorrect answers often got 0, correct answers got the full amount. You could also have partially-correct answers using this method. This is the method I would go with.
You could go and say every question is worth 10 points or you could assign different weights to different questions:
Questions:
id
quiz
prompt
value (you can make this question worth more or less)
Answers:
question
prompt
value (you can make this answer worth more or less)
Store the correct answer in the Answers Table
A more simple (but less robust) solution is to simply say which answer is correct in the Answers table.
Answers:
question
prompt
is_correct
Store the correct answer in the Questions Table
I wouldn't recommend it. When you create a question, it won't have a correct answer until you insert one. This means at least 3 queries to correctly make a question. If you use foreign key dependencies, this will quickly get annoying.
Go with option 1 where you are having one row for each question/options/answer.
Option 2 does not make any sense. Every time you want to add/delete a question you'll be modifying the database schema!! And you'll have just one row always !!
Go for your first option. It is the most normalised option, but that isn't necessarily a clinching argument. But the virtues of the normalised design are manifold:
it is a piece of cake to include new questions into your quiz portfolio. (The other option requires adding new columns to the table).
it is simple to write the select statement which returns the result set. (the alternative option requires a dynamic SQL)
it is easy to write a GUI which displays the questions and answers, because each displayed set of text maps to the same coilumn_names.
Related
I have a simple form that asks "how are you doing right now at this moment?" and they select #1-10 from a dropdown.
The challenge: the user will answer this question endlessly over time, and I'd like to, if possible, store their ongoing answers in 1 column of a record with their unique user_id. Since they can potentially have hundreds of submissions to the question, what would the best way to store and retrieve their stored answer? There will be an option for them to view their past 5, 10, or even 100 answers so they can see a pattern over time how they're doing. Their info would be displayed probably in a table going across the screen like:
Here's how you've been doing:
2 4 8 9 4 9 4 etc etc
Is there a way, and is it in this case recommended, to save all their submitted answers to the question in 1 single table row column? If so, can you give me an idea of the mysql code to save ... and code to retrieve it? I would create x # of columns to save each answer if there was a known total, but in this case, we don't know how many there will be.
I wasn't able to find a solution to online.
Yes , according to the Jeff, If I were you, I will create some table that we call it temporary_answer with the field,
user_id, question_id, answer_id, created_datetime
And you will able to fetch this temporary answer anytime, anywhere by filtering the user_id and created_datetime. I have done with this when I was developing e-learning sites. I hope this answer can help.
CMIIW.
I'm aware this is normally a bad idea, and I've done my reading - in particular, this question.
However the total normalisation route seems more complex and will give me and my code more hoops to jump through. Here's my scenario:
I'm building a test creation system where users can create tests, questions and answers, and associate them all together, i.e. associate answers with questions, and questions with tests. This approach means there's no hard-linking any one kind of data to any other; a given question can be part of two or more tests, for example. So, I was thinking (simplified):
Tests table:
id (PK)
name (varchar)
questions (com-sep list of question IDs)
Questions table:
id (PK)
question text (varchar)
answers (com-sep list of answer IDs)
Answers table:
id (PK)
answer text (varchar)
So a given row in the tests table might look like:
---------------------------------------
| ID | NAME | QUESTIONS |
---------------------------------------
| 1 | SOME TEST | 1,4,7,8,11,19 |
---------------------------------------
Then, when I fetch a test and its questions, I just do some magic with group concat.
Question: is this all a bad idea? It seems a lot simpler than the alternative which is to have two further tables dedicated, respectively, to logging associations between tests and questions, and questions and answers, meaning more tables involved in any queries.
Yes, it probably is a bad idea.
Why do you think of having two more whole tables (whoa!!) as a big deal? It really isn't.
Anyway, if you're really definitely never going to want to do something like "find out which tests question 3 appears in" then go nuts, but the moment you do find you have to do something like that you'll wish you had just done it the right way.
And how will you make sure that your data is even halfway sensible? If 564 appears as an entry in one of your comma-separated lists, will you be sure that there is definitely a question number 564 in the Questions table, that it hasn't been deleted since? What a lot of extra complication to avoid creating two tables. If you don't like typing the SQL to perform the joins, you could just use an ORM.
Sure, there are cases when denormalization is worthwhile.
But keep in mind that denormalization helps simplify a subset of queries against your data, at the expense of all other queries.
The scenarios listed in my answer to Is storing a delimited list in a database column really that bad? show how many other types of queries or updates you might have to do against your data. Searching, sorting, inserting, deleting... Also, relying on referential integrity to avoid your data turning to a collection of orphans.
But if you know that fetching or updating the whole list of id's is the only thing you need to optimize for, and this will never change (famous last words), then go for it, use denormalization.
If you want any of those other types of queries to be convenient or efficient, stick with a normalized design.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Today I was working on my website and I asked myself a simple question.
Does storing an array with all informations is better than saving those one in different fields?
For example if I store a word, a password and a number in one field on the database in this way
+-------------+----------------------------------------------------------------+
| Field | Value |
+-------------+----------------------------------------------------------------+
| all | ["test","fa26be19de6bff93f70bc2308434e4a440bbad02","25468684888"] |
+-------------+----------------------------------------------------------------+
Is it better than saving it in this way?
+-------------+------------------------------------------+
| Field | Value |
+-------------+------------------------------------------+
| word | test |
| password | fa26be19de6bff93f70bc2308434e4a440bbad02 |
| number | 25468684888 |
+-------------+------------------------------------------+
I think that the first method is faster than the last one because you need only to SELECT one field and not three or more. What do you think about it?
The second method. By far.
You should never put more than one piece of data into a single column.
A single row of data shuld contain all the information you need:
id name password
1 Fluff itsASecret
2 Flupp Ohnoes
Basically, it has to do with updates, selects, searches and pretty much everything that databases do. They are made to do it on single columns, not little bits of data inside a string.
Taking your example, how do you update the password? How do you put an index on the user ID?
What if you also had a bit of data called "NumberOfVotes" If you had it all in one column in a pseudo-array, how do you get a tally of all the votes cast by all users? Would you REALLY want to pull each entry out into PHP, explode it out, add it to the running total and THEN display how many votes have been cast? What if you had a million users?
If you store everything in a ingle column, you could do a tally really easily like this:
select
sum(NumberOfVotes)
from
yourTableName
Edit (Reply to faster query):
Absolutely not, the time it takes to compelte a query will come down to two things:
1) Time it takes to execute the query
2) Time it takes to return all the data.
In this case, the time it takes to return the data will be the same, after all, the database is returning the same amount of bytes. However, with tables that are properly set up, just FINDING the right data will be faster by orders of magnitue.
As an example of how difficult it would be to simply USE a table that has the various bits of information all mumbled together, try to write a query to update the "number" value in the row that starts with the word "test".
Having said that, there are possibly some potential cases where it can in fact be okay to store multiple "fields" of data in one column. I once saw (and copied) an exceptionally interesting permissions system for users that stored the various permissions in binary and each digit in the number equated to being allowed/not being allowed to perform a certain type of action. That was however one interesting example - and is pretty much what I would call an exception that proves the rule :)
I think that the first method is faster
is your main problem actually. You are comparing solutions from only "is it faster" point of view. While you have no measure to tell if there is any difference at all. Or, if even there is, if such a difference does matter at all. So, the only your reason is a false one. While you completely overlook indeed important, essential reasons like proper database design.
Saving in separate fields is a lot more flexible as you are then able to easily search/manipulate data using SQL queries, whereas if they were in an array you would frequently find yourself needing to parse data outside SQL. Consider the following example:
+-------------+----------------------------------------------------------------+
| Field | Value |
+-------------+----------------------------------------------------------------+
| all | ["1","fa26be19de6bff93f70bc2308434e4a440bbad02","25468684888"] |
+-------------+----------------------------------------------------------------+
Using the above table, you need to find the number field for the user with id 1, however there is nothing to search for, you can't simply to a query for the value 1 somewhere in the all field, as that would find every instance of the number 1!
You'll also encounter this problem when changing data in your DB, as you'll have to get the current array, parse it, change the value, then reinsert it.
Also you'll need to put some form of ID as a field to act as a primary key.
However with separate fields for each value, it's fairly simple:
+-------------+------------------------------------------+
| Field | Value |
+-------------+------------------------------------------+
| id | 1 |
| password | fa26be19de6bff93f70bc2308434e4a440bbad02 |
| number | 25468684888 |
+-------------+------------------------------------------+
SELECT `number` FROM mytable WHERE id = 1
The second option is better because its more readable and maintainable.
If someone who didnt write the code has to maintain it, the first option is terrible.
If you ever need to change a field, or add a field, likewise, the first option is a nightmare.
The second option requires much less work.
Keep it simple!
I think given example is trivial and that's why answer for specific example is 2nd method. But there are time's when first method is far more easy to implement. For example you create pages for website dynamically from admin panel, and in start you don't know all the values that will be used in every page. So you put general options like in 2nd method, and put something like page_data and use it to store serialized object. Now you should use serialized object for data that are not likely to change individually, as they are treated as single piece of data.
In your code you fetch serialized object, do unserialize and use them as normal. This way you can add page specific data that are not generalized for every page, but still the page's are the same.
I have a game. In the game, people make many choices out of 2 options.
The choice can be either right or wrong and I am storing the result of their run through the game (which can be a very large length) as a string with 1 for a right answer and 0 for wrong answers.
So for example, player 128937 will have stored in his run column the string 00010101010010001010111 as a varchar(5000).
Is there a better way I can store this information in MYSQL? (I am using PHP too if that can help)
I would create a new table (say it's called 'answers') with three columns:
question_id,user_id and answer (which will hold values of 0/1 )
every time the player answers a question you INSERT a new entry to this table.
This way it'll be easier to maintain the sum of right/wrong answers
Why not use a tinyint(1) for each option rather than using strings?
I would make multiple tables
choices
id
scenario (or other title)
options
id
choice_id
title (example: "go left" or "turn around and go home"
correct (0 or 1)
user_choices
user_id
option_id
choice_id (optional since choice_id is already in options table)
Im creating an optimized database for online exam module.
I have two choices:
Schema with which Im storing the question, options and answer in same row.
Table: questions
Col: q_id, question, opt1, opt2, opt3, opt4, opt5, ans
Schema with which Im having 3 different tabled for each operation.
Table: questions
Col: q_id, question
Table: options
Col: q_id, opt_id, option
Table answers
Col: q_id, ans
Schema 2 is more along the lines of what you should be aiming for.
There could be a 3rd option:
q_id | question | options | answer
where the option column is of type text and stores a serialized array or json.
For the 2 options you provided: the 2nd one world be the weapon of choice
I would use schema 2, as it allows you to add an arbitrary amount of answers.
You could however incorporate the answers table in the options table.
q_id | opt_id | option | correct
In this way you can also have multiple correct answers per question.
Schema 2 would be the better option if you want to stay flexible in your exam options.
However, if you are sure you can set a fixed amount of questions every time, you might want to consider putting table "questions" and "options" into one and just having the answers vary for each user.
If there is a fixed number of answers schema 1 would be better
but if the question may have any number of answers this would be better
question_id,question,answer_id_of_the_solution
answer_id,question_id,answer