-3

以下に、Session、Question、Answer、Option_Typeの4つのデータベーステーブルがあります。

セッションテーブル:

SessionId  SessionName
1          AAA

質問表:

SessionId   QuestionId  QuestionContent       OptionId
1           1           What is 1+1 and 4+4   2
1           2           Does 2+2 = 4          26
1           3           What is 3+3 and 5+5   3

回答表:

AnswerId  SessionId QuestionId  Answer
1         1         1           B
2         1         1           C
3         1         2           Yes
4         1         3           A
5         1         3           C

Option_Type

OptionId OptionType
1        A-C
2        A-D
3        A-E
4        A-F

.... goes up to 24 where it goes up to A-Z

25       True or False
26       Yes or No

ここのjsfiddleで、ここに表示されるデモhtmlテーブルを作成しました

ここで、htmlテーブルをよく見ると、私がやろうとしているのは、「不正解」列の下に不正解を表示することであることがわかります。

たとえば、質問1の場合、データベーステーブルを見ると、質問1の「OptionId」は2です。つまり、「Option_Type」テーブルの下の「OptionId」を検索すると、「OptionTypeこのOptionIdの「」は「AD」です。したがって、オプションは「A」、「B」、「C」、および「D」です。質問1の答えは「B」と「C」です。したがって、これらの回答は正しいので表に表示したくありませんが、他のオプション「A」と「D」は正しくないので表示したいと思います。

これは意味がありますか?私の質問は、事実上、「不正解」列の下に正解を表示できず、代わりに、以下のコードの質問ごとにこの列の下に他のオプションを表示する方法です。

   $query = "SELECT q.SessionId, s.SessionName, q.QuestionId, q.QuestionContent, an.Answer, q.QuestionMarks 
   FROM Session s 
   INNER JOIN Question q ON s.SessionId = q.SessionId
   JOIN Answer an ON q.QuestionId = an.QuestionId AND an.SessionId = q.SessionId
   WHERE s.SessionName = ?
   ORDER BY q.QuestionId, an.Answer
   ";

   // prepare query
   $stmt=$mysqli->prepare($query);
   // You only need to call bind_param once
   $stmt->bind_param("s", $assessment);
   // execute query
   $stmt->execute(); 


       // This will hold the search results
    $searchQuestionId = array();
    $searchQuestionContent = array();
    $searchAnswer = array();
    $searchMarks = array();

    // Fetch the results into an array

   // get result and assign variables (prefix with db)
   $stmt->bind_result($dbSessionId, $dbSessionName, $dbQuestionId, $dbQuestionContent, $dbAnswer, $dbQuestionMarks);
      while ($stmt->fetch()) {
        $searchQuestionId[] = $dbQuestionId;
        $searchQuestionContent[] = $dbQuestionContent;
        $searchAnswer[] = $dbAnswer;
        $searchMarks[] = $dbQuestionMarks;
      } 

?>      

</head>

<body>

<form id="QandA" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>" method="post">

<?php 

echo "<table border='1' id='markstbl'>
      <tr>
      <th class='questionth'>Question No.</th>
      <th class='questionth'>Question</th>
      <th class='answerth'>Incorrect Answer</th>
      <th class='answermarksth'>Penalty per Incorrect Answer</th>
      </tr>\n";
$previous_question_id = null;
$rowspans = array_count_values($searchQuestionId);
foreach ($searchQuestionContent as $key=>$question) {

    // removed logic, not necessary to set empty strings if you're skipping them

    echo '<tr class="questiontd">'.PHP_EOL;

    if ($previous_question_id != $searchQuestionId[$key]) {
        echo '<td class="questionnumtd" name="numQuestion" rowspan="'.$rowspans[$searchQuestionId[$key]].'">'.htmlspecialchars($searchQuestionId[$key]).'</td>' . PHP_EOL;
        echo '<td class="questioncontenttd" rowspan="'.$rowspans[$searchQuestionId[$key]].'">'.htmlspecialchars($question).'</td>' . PHP_EOL;
    }

    echo '<td class="answertd" name="answers[]">';
    echo $searchAnswer[$key];
    echo '</td>' ;
    echo '<td class="answermarkstd"><input class="individualMarks" name="answerMarks[]" id="individualtext" type="text" /></td>' . PHP_EOL;

    // moved this to the end
    if ($previous_question_id != $searchQuestionId[$key]) {
        $previous_question_id = $searchQuestionId[$key];
    }
}
        echo '</tr>';
        echo "</table>" . PHP_EOL;

        ?>

</form>

現時点では、上記のコードは「不正解」列の下に正解を示していますが、不正解ではありません。

4

1 に答える 1

2
  1. 潜在的なオプションの表を作成します。

    CREATE TABLE Answer_Options (Answer VARCHAR(5) NOT NULL PRIMARY KEY);
    
    INSERT INTO  Answer_Options VALUES
      ('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'),
    
      ('True'), ('False'),
      ('Yes'),  ('No')
    ;
    
  2. Option_Typeレコードを次のオプションに関連付けるテーブルを作成します。

    CREATE TABLE OptionType_Options (
      OptionId TINYINT UNSIGNED NOT NULL,
      Answer   VARCHAR(5) NOT NULL,
      FOREIGN KEY (OptionId) REFERENCES Option_Type    (OptionId),
      FOREIGN KEY (Answer  ) REFERENCES Answer_Options (Answer  )
    );
    
    INSERT INTO OptionType_Options (OptionId, Answer)
      SELECT o.OptionId, a.Answer
      FROM Answer_Options a JOIN Option_Type o ON (
             o.OptionType LIKE '_-_' AND
             CHAR_LENGTH(a.Answer) = 1 AND
             a.Answer BETWEEN  LEFT(o.OptionType, 1)
                          AND RIGHT(o.OptionType, 1)
           ) OR (
             o.OptionType LIKE '% or %' AND
             a.Answer IN (
               SUBSTRING_INDEX(o.OptionType, ' or ',  1),
               SUBSTRING_INDEX(o.OptionType, ' or ', -1)
             )
           )
    ;
    
  3. Answer.Answerこの新しいテーブルへの外部キーとして列を定義します。

    ALTER TABLE Answer ADD FOREIGN KEY (Answer) REFERENCES Answer_Options (Answer);
    
  4. Option_Type必要に応じて、不要になった列から削除しOptionTypeます(ただし、人間が読める形式の「名前/コメント」タイプのメタデータとして保持すると便利な場合があります)。

    ALTER TABLE Option_Type DROP COLUMN OptionType;
    

    必要に応じて、次の方法で前のテーブルを取得できます。

    SELECT   t.*,
             CONCAT_WS(
               IF(COUNT(*) > 2, '-', ' or '),
               MIN(o.Answer),
               MAX(o.Answer)
             ) AS OptionType
    FROM     Option_Type t JOIN OptionType_Options o USING (OptionId)
    GROUP BY OptionId
    
  5. これで、可能な回答と正しい回答の間で外部結合を実行して、交差点の外側から誤った回答を判別できます。

    SELECT      Question.*,
                GROUP_CONCAT(o.Answer)                   AS  Possible_Answers,
                GROUP_CONCAT(a.Answer)                   AS   Correct_Answers,
                GROUP_CONCAT(NULLIF(o.Answer, a.Answer)) AS Incorrect_Answers
    FROM        OptionType_Options o JOIN Question USING (OptionId)
      LEFT JOIN Answer a USING (SessionId, QuestionId, Answer)
    GROUP BY    QuestionId
    

    sqlfiddleでそれを参照してください。

  6. 目的の出力を作成するには:

    $stmt = $mysqli->prepare('
      SELECT      s.SessionId,  s.SessionName,
                  q.QuestionId, q.QuestionContent, q.QuestionMarks,
                  GROUP_CONCAT(o.Answer ORDER BY o.Answer SEPARATOR 0x1e),
                  COUNT(*)
      FROM        OptionType_Options o
             JOIN Question q USING ( OptionId)
             JOIN Session  s USING (SessionId)
        LEFT JOIN Answer   a USING (SessionId, QuestionId, Answer)
      WHERE       s.SessionName = ? -- SessionId would be better
              AND a.Answer IS NULL
      GROUP BY    s.SessionId, q.QuestionId
      ORDER BY    q.QuestionId
    ') or die($mysqli->error);
    $stmt->bind_param('s', $assessment) or die($stmt->error);
    $stmt->execute() or die ($stmt->error); 
    
    if (!$stmt->num_rows) die ('No results.');
    
    echo '
    <form id="QandA" method="post">
      <table border="1" id="markstbl">
        <tr>
          <th class="questionth">Question No.</th>
          <th class="questionth">Question</th>
          <th class="answerth">Incorrect Answer</th>
          <th class="answermarksth">Penalty per Incorrect Answer</th>
        </tr>
    ';
    
    $stmt->bind_result(
      $dbSessionId,  $dbSessionName,
      $dbQuestionId, $dbQuestionContent, $dbQuestionMarks
      $dbAnswers,    $rowspan
    );
    
    while ($stmt->fetch()) {
      echo 
        '<tr class="questiontd">', PHP_EOL,
          '<td class="questionnumtd" name="numQuestion" rowspan="',$rowspan,'">',
            htmlspecialchars($dbQuestionId),
          '</td>', PHP_EOL,
          '<td class="questioncontenttd" rowspan="'.$rowspan.'">',
            htmlspecialchars($dbQuestionContent),
          '</td>', PHP_EOL
        ;
    
        $first = true;
        foreach (explode(chr(0x1e), $dbAnswers) as $dbAnswer) {
          if (!$first) echo
        '<tr class="questiontd">', PHP_EOL;
    
          echo
          '<td class="answertd">',htmlspecialchars($dbAnswer),'</td>',
          '<td class="answermarkstd"><input',
            ' class="individualMarks"',
            ' name="answerMarks[',$dbAnswer,']"',
            ' id="individualtext"',
            ' type="text"',
          '/></td>', PHP_EOL,
        '</tr>';
    
          $first = false;
        }
    }
    
    echo '
        </table>
      </form>
    ';
    
于 2012-11-07T08:24:38.923 に答える