9

私は現在、PHP/MySQL を使用して調査の作成/管理 Web アプリケーションに取り組んでいます。データベース テーブルのいくつかの改訂を行ってきましたが、特定の種類の回答の保存について再考する必要があるかもしれないことに再び気付きました。

現在、次のようなテーブルがあります。

調査回答

id          PK
eid
sesid
intvalue    Nullable
charvalue   Nullable

id = 各行に割り当てられた一意の値

eid = この回答が回答するアンケートの質問

sesid = 調査の「セッション」(調査の日時に関する情報) id

intvalue = 数値の場合の回答の値

charvalue = テキスト表現の場合の回答の値

これにより、MySQL の数学関数を引き続き使用して処理を高速化することができました。

しかし、私は新たな課題を見つけました: 複数の回答を持つ質問を保存することです。例は次のとおりです。

次のうち、あなたがよく食べるのはどれですか? (該当するものをすべて選択してください)

  • ガールスカウトのクッキー
  • ベーコン
  • トウモロコシ
  • 鯨脂

今、結果を保存したいとき、それを処理する最善の方法がわかりません。現在、次のような複数選択オプションの表があります。

調査要素オプション

id        PK
eid
value

id = 各行に関連付けられた一意の値

eid = このオプションが関連付けられている質問/要素

value = そのオプションのテキスト値

このセットアップでは、返された複数選択の回答を、調査で選択された element_options 行のコンマ区切り ID の文字列として「survey_answers」に保存します。(つまり、「4,6,7,9」のようなもの)それが本当に最善の解決策なのか、それとも選択した各回答を保持する新しいテーブルを作成してから参照する方がより実用的かどうか疑問に思っています要素を参照し、最終的には調査を参照する特定の回答行。


編集

興味のある人のために、これが私が取ったアプローチです(PhpMyAdmin関係ビューで):

データベースの関係とテーブル構造

また、複数選択の質問のカウントを収集する基本的なクエリは次のようになります。

SELECT e.question AS question, eo.value AS value, COUNT(eo.value) AS count
FROM survey_elements e, survey_element_options eo, survey_answer_options ao
WHERE e.id = 19
AND eo.eid = e.id
AND ao.oid = eo.id
GROUP BY eo.value
4

4 に答える 4

6

これは本当に多くのことに依存します。

  1. 一般に、コンマ区切りの値のリストをデータベースに保存するのは良くありません。特に、そのデータをリモートでインテリジェントに処理する予定がある場合はなおさらです。特に、回答に関する高度なレポートを作成したい場合。
  2. これを格納する最善のリレーショナルな方法は、2 番目のテーブルで回答を定義し、3 番目のテーブルの質問に対するユーザーの回答にリンクすることです (ユーザーの質問ごとに複数のエントリを使用するか、場合によってはユーザーのアンケートの質問に複数のエントリを使用します)。ユーザーは、同じ質問で複数のアンケートに回答できます。

これは、単純な例として考えられるシナリオとして、少し複雑になる可能性があります。

テーブルの例:

  • Users( Username, UserID)
  • Questions( qID, QuestionsText)
  • AnswersAnswerText[この場合、例は再利用可能ですが、これにより複雑さがさらに増します]、aID
  • Question_Answers([この質問に対して利用可能な回答、質問ごとに複数のエントリ] qaID, qID, aID),
  • UserQuestionAnswers( qaID, uID)

注: 推奨ではなく、例としての意味

于 2013-02-06T23:11:07.833 に答える
2

主キーを一意ではないインデックスに変換し、同じ ID で同じ質問に対する回答を追加します。

例えば。

id  | eid | sesid | intval | charval
 3     45      30        2  
 3     45      30        4

必要に応じて、通常の一意の PK 用に別の列を追加することもできます。

物事をシンプルに保ちます。ここに関係は必要ありません。

于 2013-02-06T23:09:18.627 に答える
1

それは本当にコースの馬です。

コンマ区切りの文字列として保存できます (ただし、回答の 1 つにリテラル コンマがある場合はどうなりますか)。

次のような 1 対多のテーブルとして格納できます。

survey_element_answers

id                PK
survey_answers_id FK
intvalue          Nullable
charvalue         Nullable

そして、そのテーブルをループします。回答を 1 つ選択すると、このテーブルに 1 つの行が作成されます。2 つの回答を選択すると、このテーブルに 2 つの行が作成されます。その後、survey_answers テーブルから intvalue と charvalue を削除します。

要素のオプションを独自のテーブルに既に格納しているため、別の選択肢として、次のような多対多のテーブルを作成します。

survey_element_answers

id                         PK
survey_answers_id          FK
survey_element_options_id  FK

ここでも、選択したオプションごとに 1 行です。

もう 1 つのオプションは、ビットマスク値を格納することです。これにより、多対多テーブルの必要性がなくなります。

調査要素オプション

id              PK
eid             FK
value           Text
optionnumber    unique for each eid
optionbitmask   2 ^ optionnumber

optionnumber は eid ごとに一意である必要があり、1 から始まります。bigint を使用している場合は 63 個のオプション、int を使用している場合は 31 個のオプションの制限があります。

そして、あなたのsurvey_answersで

id            PK
eid
sesid
answerbitmask bigint

Answerbitmask は、ユーザーが選択したオプションごとに、すべての optionbitmask を合計して計算されます。たとえば、Answerbitmask に 7 が格納されている場合、ユーザーが最初の 3 つのオプションを選択したことを意味します。

結合は次の方法で実行できます。

WHERE survey_answers.answerbitmask & survey_element_options.optionbitmask > 0

そうです、考慮すべきいくつかのオプションがあります。

于 2013-02-06T23:16:21.563 に答える
-1

ID を別のクエリで外部キーとして使用しない場合、または sesid を使用して結果をクエリできる場合は、多対 1 の関係を試してください。それ以外の場合は、JSON などのシリアル化された配列として、または php の serialize() 関数を使用して、複数の選択肢の回答を保存します。

于 2013-02-06T23:09:02.723 に答える