Storing Exam Questions in a Database - sql

I've been thinking about how I should design a database to hold exam questions for a little over a year now (on and off, mostly off).
First, a short description of what I'm after. I would like to design a database flexible enough to store different question types (for example, short response or multiple choice questions), and be able to select any number of those questions to be stored as an exam.
My question is:
How should the exam questions be stored?
Since different question types require different fields to store, if I was to put them all under the same table questions, there will be a lot of extra fields that are never used.
If I separate the question types into different tables, it'll be a lot harder to store the question_id in some exam_questions table, since they will come from different tables.
I also can't think of a flexible way to store the information.
For example,
questions
- id
- question
- type (multiple choice, short response)
- choice_1 ( used for multiple choice questions)
- choice_2
- choice_3
- choice_4
- choice_5
- answer (short response answer here, or just a/b/c/d/e for multiple choice, t/f for true or false)
Would a design like this be recommended? If not, does anyone have any advice?
I also have another question:
If I want to store student responses to one of these exams, would it be inefficient to store them like this?
exam_responses
- id
- student_id
- exam_id
- question_id or question_number
- response
- mark
Thank you in advance. If you would like any other information, or if there is anything wrong with this question, please leave me a comment and I'll try and have it fixed as soon as possible.

I would have separate question and answer tables and join them using a question2answer table
question
--------
- id
- question
- type (multiple choice, short response)
answer
------
- id
- GUIorder (so you can change the sort order on the front end)
- answer
question2answer
---------------
- questionid
- answerid
Now everything is dynamic in terms of building the question and you don't have empty columns.
A quick join brings you back all the parts to the main question
Your exam_responses table can now have the following
- id
- questionid
- answerid
- studentid
- response
- mark

I think storing five columns for each response in the questions table is not a good design. If the number of choices for the question becomes 6 you will have to add one more column. Also, if there are just two choices, the remaining columns will stay empty. So it better be in two separate tables:
questions
- id
- question
- type (multiple choice, short response)
- answer (short response answer here, or just a/b/c/d/e for multiple choice, t/f for true or false)
question_choices
- id
- question_id
- choice
Then you can get the list of choices for each particular question by joining them based on questions.id=question_chocies.question_id condition.
In case of exam responses, you should divide in two tables too in order not to repeat information about student_id, exam and mark for each question of the exam. So it should be something like:
student_exam
- id
- student_id
- exam_id
- mark
student_exam_responses
- exam_id
- question_id or question_number
- response
These two tables can be connected based on the student_exam.id=student_exam_responses.exam_id condition.

Related

What would be the best way to store checkboxes in SQL

Hello Community from a Newbie;
I haven't found anything like this here with the search function so I hope it's not a stupid question . ( And sorry for my bad english ) .
I've planned to do a checklist with checkboxes in it (over 30 I think). I'm now thinking about how to store the status ( check or not checked ) into my SQL Database and read it out .
Plan A :
For each Checkbox I'll put a Column in the database, which sounds like an easy way but I think there has to be a better way in sense of Performance
Plan B : like an binary code in a single Column - like 00100 - means that just the 3rd Checkbox is a checked Checkbox . Makes more sense to me but give me a little bit the feeling that it is hard to code especially in case of reading those checkbox list out from SQL again like
if (00100 == 00010) checkbox2.checked;
if (00100 == 00100) checkbox3.checked;
I hope you can help a C# Newbie and give me maybe some other Solutions Ideas.
Thank you All
Greetings from Austria
So, there is a lot to unpack here. Basically, you are asking how to structure a database table.
IMHO Plan B is not a road you would like to go down. It will be quite confusing to anyone trying to make sense of it in the future. With respect to the table, it depends on your checklist.
Plan A is too static. Will that list change(grow or shrink)? When you talk about storing checks, you are storing responses. This begs the question how will you be storing the actual questions?
I would probably create two seperate tables, one for questions, and the other for responses.
This may seem a little overboard at first from your perspective but it allows you change your checklist over time.
Modeling-wise my question table might look like this:
table: questions
columns: content, order
table: responses
columns: question_id, user_id, checked:boolean

SQL Server - Q&A Engine

I'm investigating the possibility of writing a web-based question and answers engine to assist my girlfriend in her line of work.
What I mean by "question and answers" engine is, that the database (and ultimately user interface) can present many styles of question to an end user - not specifically multiple choice, the questions could be "fill in the blank(s)" or "sqrt(189) equals" or "change the words in the paragraph" or a "word-search" style question with many correct answers.
As a more specific example, if a question was "fill in the missing words: 'the ____ brown ____ jumps over the ____ dog'" and the user is presented with various answers. Likewise, another specific answer could be "list as many words you can make from the word: 'antidisestablishmentarianism'".
Having done some searches already on stackoverflow, there have been some similar questions raised however none seemed to fit the mould of what I'm wanting.
As I see it, I can have a single questions table...
TABLE Questions
QuestionID UNIQUE INT
Question NTEXT // The question text (could include markup for web)
Options NTEXT // Could be a CSV list of possible options (for multi-choice type questions)
QuestionTypeID INT // ID of the question type record (more for the user-interface)
TABLE QuestionTypes
QuestionTypeID UNIQUE INT
Description NVARCHAR(100)
TABLE Answers
AnswerID UNIQUE INT
UserID INT // Related User record
QuestionID INT // Related Question record
Answers NTEXT // Could this be a CSV list of answers??
I can see how the above would work for very simple, single or multiple choice answers but I'm not sure how it would work for different styles of question.
Another thought I had was having different tables handling different QuestionTypeID values, for example:
TABLE QuestionType1 // Table styled to question type 1
QuestionType1ID UNIQUE INT
QuestionID INT // Related question record
...
TABLE QuestionType2 // Table styled to question type 2
QuestionType2ID UNIQUE INT
QuestionID INT // Related question record
...
But I can't really see how this would work. Am I thinking about this or approaching it in the wrong way?
I'd appreciate any help (if the question makes sense in the first place)!
Regards,
K

Transpose SQL table when the value is text

I have a table containing a series of survey responses, structured like this:
Question Category | Question Number | Respondent ID | Answer
This seemed the most logical storage for the data. The combination of Question Category, Question Number, and Respondent ID is unique.
Problem is, I've been asked for a report with the Respondent ID as the columns, with Answer as the rows. Since Answer is free-text, the numeric-expecting PIVOT command doesn't help. It would be great if each row was a specific Question Category / Question Number pairing so that all of the information is displayed in a single table.
Is this possible? I'm guessing a certain amount of dynamic SQL will be required, especially with the expected 50-odd surveys to display.
I think this task should be done by your client code - trying to do this transposing on SQL side is not very good idea. Such SQL (even if it can be constructed) will likely be extremely complicated and fragile.
First of all, you should count how many distinct answers are there - you probably don't want to create report 1000 columns wide if all answers are different. Also, you probably want to make sure that answers are narrow - what if someone gave really bad 1KB wide answer?
Then, you should construct your report (would that be HTML or something else) dynamically based on results of your standard, non-transposed SQL.
For example, in HTML you can create as many columns as you want using <th>column</th> for table header and <td>value</td> for data cell - as long as you know already how many columns are going to be in your output result.
To me, it seems that the problem is the number of columns. You don't know how many respondents there are.
One idea would be to concatenate the respondent ids. You can do this in SQL Server as:
select distinct Answer,
(select cast(RespondentId as varchar(255))+'; '
from Responses r2
where r2.Answer = r.Answer
for xml path ('')
) AllResponders
from Responses r
(This is untested so may have syntax errors.)
If reporting services or excel power pivot are possibilities for the report then they could both probably accomplish what you want easier than a straight sql query. In RS you can use a tablix, and in power pivot a pivot table. Both avoid having to define your pivot columns in an sql pivot statement, and both can dynamically determine the column names from a tabular result set.

Should I avoid loops in joins?

I remember I was taught to never create a loop when joining tables in sql.
In effect, using Business Objects it even tells me if there are loops in the schema I've defined in the Universe.
I've tried to search on the web about this statement but I wasn't able to find a reference.
Why is it dangerous to do this?
Edit: maybe I was too succint.
My question wasn't about looping intended as a "FOR LOOP" or similar.
I was talking about something like this WHERE clause in a SELECT statement:
WHERE TABLE1.foo = TABLE2.foo
AND TABLE2.bar = TABLE3.bar
AND TABLE3.baz = TABLE1.baz
if you draw the relation you will see "a loop" in the join.
Is this dangerous from a correctness and/or performance point of view?
Thanks to all.
Edit 2: added an example.
I've just thought an example, maybe it isn't the best, but I think it will serve to understand.
------------ ----------------- ----------------------
- DELIVERY - - DELIVERY_DATE - - DELIVERY_DETAILS -
------------ ----------------- ----------------------
- id - <--- - id - <----- date_id -
- company - |----- delivery_id - - product -
- year - - date - - quantity -
- number - ----------------- - datetime_of_event -
- customer - ----------------------
- ----------
1 <-----> N 1 <----> N
In the DELIVERY table every delivery appears only once
In the DELIVERY_TABLE we have the list of every date in which the delivery was processed. So, a delivery may be prepared in several days.
In the last table we have the details of every delivery. So, in this table we track every event related to the preparation of the delivery
So, the cardinalities are 1:N for each couple of tables.
The join is very simple:
DELIVERY.id = DELIVERY_DATE.delivery_id AND
DELIVERY_DATE.id = DELIVERY_DETAILS.date_id
Now, suppose I want to join another table, where I have some other information for a delivery in a certain date.
Let's define it:
------------
- EMPLOYEE -
------------
- company -
- year -
- number -
- date -
- employee -
------------
Now the join should be:
DELIVERY.id = DELIVERY_DATE.delivery_id AND
EMPLOYEE.company = DELIVERY.company AND
EMPLOYEE.year = DELIVERY.year AND
EMPLOYEE.number = DELIVERY.number AND
EMPLOYEE.date = DELIVERY_DATE.date
To sum up, I'll end having EMPLOYEE joining both DELIVERY and DELIVERY_DATE, having the cycle in the join.
Should I rewrite it in this way?
EMPLOYEE.company = DELIVERY.company AND
EMPLOYEE.year = DELIVERY.year AND
EMPLOYEE.number = DELIVERY.number AND
EMPLOYEE.date IN (SELECT date FROM DELIVERY_DATE d WHERE d.delivery_id = DELIVERY.id)
Edit 3: finally found a link
As usual, when you've given up searching for a link, you find it.
So, this article explains all. It's related to Business Objects, but the content is generic.
Thanks to all for your time.
EDIT: I see from the update that this is an issue that's specific to a BO designer, where a table is used more than once, but BO automatically combines join clauses, which then incorrectly (or, rather, unintentionally) restricts the result set. This question actually has nothing to do with cycles, per se, it's really about using entities in more than one context in the same query. I'll leave my original answer below, even though it doesn't really address OP's concern.
Disclaimer: This is a non-answer answer, because it's both an answer and a question. It probably should be a comment, but you can't comment unless you ask/answer questions, but since I genuinely want to help, I'll do it the only way I can, even if it's not the way things are done here. So sue me.
The short answer is no, you shouldn't avoid loops (or "cycles") in joins.
More to the point, queries are constructed so as to declare the correct logical condition(s) to produce the data you're looking for. The same logical condition can often be established in many different ways, so sometimes it makes sense to ask if one way is preferable to another. This becomes of particular interest when performance is important. But first and foremost a query must return the right result set. How this is accomplished depends on the underlying schema. And this is what you really should be focused on.
In your example, why role does EMPLOYEE play regarding the DELIVERY tables? Why would you join on those columns? What would that mean that an EMPLOYEE has the same "date" as a delivery? I understand it's a contrived example, but the point I'm trying to make is that whether joins create a cycle in the graph or not is wholly (well, principally) dependent on what a particular result set's logical meaning is.
And on the issue of JOIN syntax, using JOIN...ON clauses is preferable to WHERE clauses because it separates what you need to do to combine entities from data filtering operations.
Well, your question is easy. You should not be using where clauses to perform joins. You should be using on clauses. Your joins can be expressed as:
from Table1 join
Table2
on Table1.foo = Table2.foo join
Table3
on Table2.bar = Table3.bar and
Table1.baz = Table3.baz
Whether this is appropriate or not depends on your data structures. Sometimes it is. You shouldn't worry about it.
By the way, I wouldn't refer to this as "loops" which is very associated with "for loops" in programming and nested loop joins in SQL. You might refer to this as cycles in join conditions.
Wmax . . . as for the new join syntax. It is not "just" a matter of taste. The "," in a from clause means "cross join". This is a very expensive operation, in most cases. It is much better to be clear about what you want to accomplish:
FROM A cross join B
is much clearer about its intentions than:
FROM A, B
Second, if you leave the "," out, you still have valid syntax:
FROM A B
However, this means something very different (assigning the alias B to the table A).
The third reason is the most important reason. The old syntax does not have a way of expressing left outer join, right outer join, and full outer join.
So, to write clearer queries, to avoid errors, and to access better functionality, you should learn the new syntax.

What are best practices for multi-language database design? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
What is the best way to create multi-language database? To create localized table for every table is making design and querying complex, in other case to add column for each language is simple but not dynamic, please help me to understand what is the best choose for enterprise applications
What we do, is to create two tables for each multilingual object.
E.g. the first table contains only language-neutral data (primary key, etc.) and the second table contains one record per language, containing the localized data plus the ISO code of the language.
In some cases we add a DefaultLanguage field, so that we can fall-back to that language if no localized data is available for a specified language.
Example:
Table "Product":
----------------
ID : int
<any other language-neutral fields>
Table "ProductTranslations"
---------------------------
ID : int (foreign key referencing the Product)
Language : varchar (e.g. "en-US", "de-CH")
IsDefault : bit
ProductDescription : nvarchar
<any other localized data>
With this approach, you can handle as many languages as needed (without having to add additional fields for each new language).
Update (2014-12-14): please have a look at this answer, for some additional information about the implementation used to load multilingual data into an application.
I recommend the answer posted by Martin.
But you seem to be concerned about your queries getting too complex:
To create localized table for every table is making design and querying complex...
So you might be thinking, that instead of writing simple queries like this:
SELECT price, name, description FROM Products WHERE price < 100
...you would need to start writing queries like that:
SELECT
p.price, pt.name, pt.description
FROM
Products p JOIN ProductTranslations pt
ON (p.id = pt.id AND pt.lang = "en")
WHERE
price < 100
Not a very pretty perspective.
But instead of doing it manually you should develop your own database access class, that pre-parses the SQL that contains your special localization markup and converts it to the actual SQL you will need to send to the database.
Using that system might look something like this:
db.setLocale("en");
db.query("SELECT p.price, _(p.name), _(p.description)
FROM _(Products p) WHERE price < 100");
And I'm sure you can do even better that that.
The key is to have your tables and fields named in uniform way.
I find this type of approach works for me:
Product ProductDetail Country
========= ================== =========
ProductId ProductDetailId CountryId
- etc - ProductId CountryName
CountryId Language
ProductName - etc -
ProductDescription
- etc -
The ProductDetail table holds all the translations (for product name, description etc..) in the languages you want to support. Depending on your app's requirements, you may wish to break the Country table down to use regional languages too.
I'm using next approach:
Product
ProductID OrderID,...
ProductInfo
ProductID Title Name LanguageID
Language
LanguageID Name Culture,....
Martin's solution is very similar to mine, however how would you handle a default descriptions when the desired translation isn't found ?
Would that require an IFNULL() and another SELECT statement for each field ?
The default translation would be stored in the same table, where a flag like "isDefault" indicates wether that description is the default description in case none has been found for the current language.