DB Table Structure:
Session Table (aka Exam Table)
SessionId(auto) SessionName
137 XULWQ
Question Table:
SessionId QuestionId OptionId
137 1 5
137 2 2
Option_Table Table:
OptionId OptionType
1 A-C
2 A-D
3 A-E
4 A-F
5 A-G
6 A-H
7 A-I
8 A-J
9 A-K
10 A-L
11 A-M
12 A-N
13 A-O
14 A-P
15 A-Q
16 A-R
17 A-S
18 A-T
19 A-U
20 A-V
21 A-W
22 A-X
23 A-Y
24 A-Z
25 True or False
26 Yes or No
Answer Table:
AnswerId(auto) SessionId QuestionId Answer
200 137 1 B
201 137 1 D
202 137 2 F
203 137 2 A
204 137 2 C
I want to create a page where I want it to display the incorrect answers per question.
I am thinking of doing it by retrieving the each question's option type, display the all the letter answers belonging to the option type, and then remove the correct answers from the letter answers so that it is left with incorrect answers only.
options array:
$option = array();
$option[1]= array(A,B,C);
$option[2]= array(A,B,C,D);
$option[3]= array(A,B,C,D,E);
...
$option[23]= array(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y);
$option[24]= array(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z);
$option[25]= array(True,False);
$option[26]= array(Yes,No);
My question is that I need help after this section. How do I start retrieving the wrong answers after this array using mysqli/php and the database I currently have?
UPDATE:
Below shows the sql which displays the correct answers for each question:
SELECT
q.QuestionContent,
o.OptionType,
q.NoofAnswers,
GROUP_CONCAT(DISTINCT Answer ORDER BY Answer SEPARATOR '') AS Answer,
r.ReplyType,
q.QuestionMarks
FROM Question q
LEFT JOIN Answer an
ON q.QuestionId = an.QuestionId
LEFT JOIN Reply r
ON q.ReplyId = r.ReplyId
LEFT JOIN Option_Table o
ON q.OptionId = o.OptionId
group by q.QuestionContent
See SQL Fiddle with Demo
This returns the result:
| QUESTIONCONTENT | OPTIONTYPE | NOOFANSWERS | ANSWER | REPLYTYPE | QUESTIONMARKS |
----------------------------------------------------------------------------------------
| Name these 2 flowers | A-F | 2 | C | Multiple | 5 |
| What is 2+2? | A-D | 1 | ABD | Single | 5 |
Your problem is that, the way your Option_Table
is designed, decoding the OptionType
column to find out all the possible answers requires some nontrivial external knowledge.
(Indeed, you haven't provided enough information in your question for me to be sure exactly how to do that; I can make a guess for those OptionTypes
which you've shown me, but I can't be sure if there are, or could be, others.)
It would be better to replace (or at least augment) that table with a simpler table which, for each OptionId
, simply lists all the possible options, like this:
CREATE TABLE Options (
OptionId INTEGER NOT NULL,
OptionAnswer CHAR(1) NOT NULL, -- or whatever type Answer.Answer has
PRIMARY KEY (OptionId, OptionAnswer)
);
INSERT INTO Options VALUES
(1, 'A'), (1, 'B'), (1, 'C'),
(2, 'A'), (2, 'B'), (2, 'C'), (2, 'D'),
-- ...
(25, 'T'), (25, 'F'),
(26, 'Y'), (16, 'N');
Then you can find all the right and wrong answers for each question with a query like this:
SELECT
q.QuestionContent,
q.NoofAnswers,
GROUP_CONCAT(DISTINCT Answer ORDER BY Answer SEPARATOR '') AS RightAnswers,
GROUP_CONCAT(DISTINCT
CASE
WHEN Answer IS NULL THEN OptionAnswer
ELSE NULL
END
ORDER BY OptionAnswer SEPARATOR '') AS WrongAnswers,
r.ReplyType,
q.QuestionMarks
FROM Question q
LEFT JOIN Reply r
ON q.ReplyId = r.ReplyId
LEFT JOIN Options o
ON q.OptionId = o.OptionId
LEFT JOIN Answer an
ON q.QuestionId = an.QuestionId AND o.OptionAnswer = an.Answer
GROUP BY q.SessionId, q.QuestionId
Here's a demo of it on SQLize (slightly altered to skip columns not included in your example tables).
Edit: An alternative solution would be to construct the list of wrong answers in PHP. For example, if $row
is an object (as returned e.g. by mysqli_fetch_object()
) containing a single row from your original query, you could compute the wrong answers like this:
// Do this (preferably) before looping over the rows:
$specialOptionTypes = array(
'Yes or No' => array( 'Y', 'N' ),
'True or False' => array( 'T', 'F' ),
);
// Do this for each row:
if ( array_key_exists( $row->OptionType, $specialOptionTypes ) ) {
$options = $specialOptionTypes[ $row->OptionType ];
} else if ( preg_match( '/^([A-Z])-([A-Z])$/', $row->OptionType, $match ) ) {
$options = range( $match[1], $match[2] );
} else {
// issue warning about unrecognized option type
$options = array();
}
$right = str_split( $row->Answer ); // or explode() on a delimiter, if any
$wrong = array_diff( $options, $right );
$row->WrongAnswers = implode( '', $wrong ); // if you actually want a string
Here's a demo on ideone.com, based on your sample query output.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With