データベースに長けた方にお聞きします。


設問数、回答形式不特定のアンケートを作成しているのですが、データベースの仕様で悩んでいます。
アンケートは設問数が一定でなく (最大 50 程度)、回答形式もそれぞれ択一、複数選択、テキストと固定されていません。
これを賄うのにどういった DB 設計が望ましいのでしょうか。

案 1. 回答形式に応じたテーブル (radio,checkbox,text..) を作成する。1 回答 = 1 レコードで処理。
案 2. アンケートを アンケート種別 -> 個別アンケート といったヒエラルキーで縛り、アンケート種別をフォーマットフリーにしてそれに応じたテーブルを作成する。1 アンケート = 1 レコードで処理。

案 1 の場合、設問数 50 で複数選択が入った場合、最悪 70 近い INSERT 文を発行する事になりパフォーマンスが心配です。
案 2 の場合、カラム数が 100 近くに達する可能性があり、DB 設計的に妥当なのかどうか不安です。

といった状況なのですが、何かご助言いただける事があればお願いいたします。

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:2004/10/05 01:29:17
  • 終了:--

回答(8件)

id:teatime_miki No.1

teatime_miki回答回数88ベストアンサー獲得回数02004/10/05 02:20:17

http://www.hatena.ne.jp/1096907357#

データベースに長けた方にお聞きします。 設問数、回答形式不特定のアンケートを作成しているのですが、データベースの仕様で悩んでいます。 アンケートは設問数が一定でな.. - 人力検索はてな

私がDB設計するのであれば、

・1回答=1レコードで処理。

・1カラム=1設問で処理。

・すべてテキストで固定。

・択一、複数選択の場合は書式を決めてテキスト形式で保存する。

(例 択一:radio-a 選択:check-a,d,gのような。)

・・・という形にすると思います。

レコードに、radioとかcheckのように決まった言葉があれば、択一や複数選択の設問であるということがわかるようにすれば、択一でも複数選択でもテキスト形式でも保存できるのではないでしょうか?

そうすれば、複雑なテーブル設計をしなくても処理できそうな感じがしますがいかがでしょうか?

id:hebe

それをやるとデータベースを使う意味が無いと思うのですが、それなら XML に落として集計に musashi かスクリプト作ってやります

2004/10/05 13:58:33
id:hempire No.2

hempire回答回数19ベストアンサー獲得回数02004/10/05 02:30:51

ポイント60pt

http://it-ura.seesaa.net/

IT業界の裏話

アンケートの集計はリアルタイムで行う必要がありますか?DBへのデータ格納が非同期でよいのであれば、送信されたアンケート内容を、「Seq,送信内容」の仮テーブルに格納しておき、あとで個別のテーブルに振り分けてやるというのはどうですか?

サーバ上に時次で実行されるSPを用意しておけば、オンラインパフォーマンスへの影響はほぼありません。

回答頻度や1レコードの長さ、サーバ/クライアントの関係やそのスペックなどの詳しい状況が分からないので抽象的な回答になりましたが、正規化のしすぎによるパフォーマンス劣化が起きないようご注意下さい。

id:hebe

なるほど、良いヒントを頂きました。ありがとうございます。

2004/10/05 13:59:20
id:upride No.3

upride回答回数220ベストアンサー獲得回数12004/10/05 02:33:22

ポイント30pt

設問数や質問の形式が普遍ならば案2でも宜しいと思いますが

質問の改訂があった場合ちょっとひどいことになりそうですね

設問の種類が複数ある場合でもテーブルは統一のほうがメンテしやすいのではないかと思います

この2テーブル案はどうでしょうか

[アンケートテーブル]

アンケートID 、更新年月日、ユーザ名

1、’2004/10/01’、’guest’

[アンケート詳細テーブル]

アンケートID 、設問ID 、問題形式、回答1 、 回答2 、回答3・・・

1、1、’text’、’あああ’、null 、null

1、2、’radio’、’1’、null 、null

・・・・

1、50、’list’、’hoge1’ 、’hoge2’ 、’hoge3’

これだと2000人のアンケートで10万レコードですね

どのDBで構築するかも吟味の必要があるかも。

id:hebe

むぅ、利用者に対するレコード数を見落としてました。厳しいですね。

2004/10/05 14:00:56
id:dekodeko No.4

dekodeko回答回数6ベストアンサー獲得回数02004/10/05 02:55:34

ポイント30pt

文だけで説明するのはかなりつらいので、わかりにくかったらすいません。

案2は絶対にお勧めできません。

案 1の最悪 70 近い INSERT 文ですが、70回程度なら心配されるほどの事はないと思うんですがどうでしょうか。

工夫すれば70回ではなくてテーブル数分のINSERT文ですむはずですし。

案3としてこんなのはどうでしょう。

設問1は択一式で回答が3

設問2は複数選択で回答がred,blue

設問3はテキストで回答が’自由意見’

だとすると回答テーブルを以下のようにします。

回答番号(INT) 設問番号(INT) 回答(VARCHAR)

1       1    3

1       2    red

1       2    blue

1       3    自由意見

.....

あと、何番の設問がどの回答形式で、選択できる値は何と何でって言う情報もデータベースに格納するようにすればかなり柔軟なシステムになると思います。

まあそこまでやる必要があるのかはわかりませんが。

id:hebe

案 2 をお勧めされない理由を知りたかったです。

2004/10/05 14:05:24
id:rapanui No.5

rapanui回答回数14ベストアンサー獲得回数02004/10/05 09:33:59

仕様をきちんと理解できていないので、ピンとはずれだったらポイントは極小で結構です。

案1、案2の折衷案が良いように思えます。ほぼ必須の選択肢ものもあるはずなので、それは1テーブルにまとめます(案2)。存在するか分からないものは個別のテーブルに分割します(案1)。

顧客がいろいろなサービスを利用しているが、顧客によって利用しているサービスはまちまち、といういうようなDBを設計する時はこの方法がとられています。

id:kuippa No.6

くいっぱ回答回数1030ベストアンサー獲得回数132004/10/05 10:25:23

ポイント50pt

http://allabout.co.jp/career/database/subject/msub_sekei.htm

データベース設計に関するサイト - [データベース]All About

URLはググっただけです。

さて、他の方の回答が開かれていないのに6番目の回答。

どれだけ重複するか心配です。

案1は問答無用に却下です。

どのようなデータベースソフトを使用するかわかりませんが、

データ格納構造がわからないからという理由だけで、

ヘッダー、明細とわけるというのは…、

インサート文のみならず、複数の回答結果を集計しようとしたとき、

何個のレコードを見に行かなきゃいけないかを考えると、

メリットが無いように思えます。

案2が普通だとおもいます。

構造的に分割する必要が無いテーブルをむりやり分割するのであれば、

カラム数が100になったぐらいはなんてことはありません。

わたしだったの案。

アンケート構造を格納したテーブル(アンケートごとの基本情報)

アンケートID,オプションテーブル使用フラグ,カラム1のデータ構造 (radio,checkbox,text..) ,……50

データ格納テーブル

アンケートID,カラム1(全部varchar格納),……50

オプションテーブル

アンケートID,カラム番号,データ

※オプションテーブル

テキストででかいデータを格納することが多いのであれば使用、なくってもいい。

むしろ無いほうがいい。

オプション数を限定できるのであれば、データ格納テーブルに、

データ格納用のフィールドをいくつかくっつけてしまう。

ってな感じでどうでしょう。

id:hebe

参考になりました、ありがとうございます。

2004/10/05 14:08:04
id:wm5775 No.7

wm5775回答回数351ベストアンサー獲得回数42004/10/05 10:27:16

http://www.hibernate.org/

hibernate.org - Hibernate

システム開発用件がよくわからないのでなんともいえませんが、このhibernateのようなオブジェクトをストレージするようなもの

それか、そこそこパフォーマンスの良いXMLデータベースを用いるとか、

cacheのようなオブジェクトとしてもリレーショナルとしても設計できるようなDBを使うとスキーマは簡単にデザインできると思います。

(1)アンケートコレクション

(2)設問コレクション

(3)設問オブジェクト

-設問タイプ(ラジオボックス、チェックボックス・・・)

  -設問

  -(選択肢)

みたいな感じでしょうか。

id:hebe

DB 選べませんので 残念っ

2004/10/05 14:08:38
id:atene1968 No.8

atene1968回答回数44ベストアンサー獲得回数02004/10/05 14:08:01

http://cbase.co.jp/index.php?page=enquete&subpage=features

アンケートASP[Cbase Corp]、簡単に使えるアンケート制作・実施・集計・抽選システム

こうした方法ではだめでしょうか?

(基本的に案 1の方法を採用する)

1.回答形式 - 大きく

①選択式 ②記入式の2つにわける

 ①選択式 ・・・ 「択一」と「複数選択」を含む。

 ②記入式 ・・・ ユーザーの回答した文章をそのままテキストとして持つ。

フォーマットは、 テキスト100文字(あくまで概算)とする。

2.レコードの各カラムの記録方法

回答形式が①選択式

 択一・・・男「1」、女「2」。

  => ”1” または”2”

 複数選択・・・複数回答可能で選択肢が5つある場合。

 Q. あなたが普段情報を得る手段は?

 本「Yes」、テレビ「Yes」、ラジオ「No」、新聞「No」、インターネット「Yes」

 => Yes「1」、No「0」に置き換える。

 回答のテキストカラムには”11001”と入る。

回答形式が②記入式

 普通に文字列として格納する。

3.この場合、以下のテーブルを準備します。

「設問」テーブル

設問番号:整数

設問内容:テキスト200文字

「回答1」テーブル

設問番号:整数(1)

ユーザ番号 :整数

回答:テキスト100文字

設問属性:整数(論理型でも可) ・・・ ①選択式は、「0」。②記入式は、「1」。

「回答2」テーブル

設問番号:整数(2)

ユーザ番号 :整数

回答:テキスト100文字

設問属性:整数(論理型でも可) ・・・ ①選択式は、「0」。②記入式は、「1」

・・・

「回答n」テーブル

設問番号:整数(n)

ユーザ番号 :整数

回答:テキスト100文字

設問属性:整数(論理型でも可) ・・・ ①選択式は、「0」。②記入式は、「1」

*回答には、 ①選択式の場合、「11001」と0.1のいずれかが入ります。

②記入式の場合、回答がそのまま入ります。

「回答」テーブルは余裕を持って問題数分を準備する。

「設問選択」テーブル

設問番号:整数

選択回答1:テキスト20文字

選択回答2:テキスト20文字

選択回答3:テキスト20文字

選択回答4:テキスト20文字

・・・

選択回答n:テキスト20文字

*選択回答は設問の回答文が入ります。

先の①選択式の選択文 本、テレビ、ラジオ、新聞、インターネットといった文字列が入ります。設問形式が①選択式の設問のみ、レコードに保存します。

選択回答は余裕を持ってカラム数を準備する。

「回答者」テーブル

ユーザ番号 :整数

ユーザ名:テキスト10文字

回答日時:日付型

それから、上のURLのページを参考にしてください。ここに実用的なアンケート構築システムの実例があります。

id:hebe

いや、問題はそれでパフォーマンスが現実的なのかどうかでして。Cbase ですか… うーん。

皆様ありがとうございました。

頂いたご意見を参考に取り敢えず DB ベースで作ってしまい、最終的な物は一時的に回答を DB にストアするか XML に直接落として処理してしまおうと思います。

感謝。

2004/10/05 14:14:47
  • id:dekodeko
    案2をお勧めしない理由

    回答4のものです。
    もう見てないかもしれませんが、一応案2をお勧めしない理由
    は単純に100カラムもあるのにCREATE文とINSERT文を間違わずに書くのが大変だからです。
    もし間違わなくても、途中で設問が変更になったとき大変です。
    設問に関するデータからCREATE文とINSERT文を作るという手段もなくはないですが、そんなことしなくても70回のINSERTなんて一瞬だと思いますよ。

    もしどうしてもINSERTが遅いようなら、データベースやミドルウエアによって一度にたくさんのINSERTを行うための独自拡張があるのでそれを利用すると良いでしょう。

    たとえば、MySQLやPostgreSQLなら(たぶん他のデータベースでも)CVS形式のファイルを読み込んでテーブルにINSERTするような構文があり、実際にこれを使って何千万件をINSERTしたことがありますが、1分もかからずに終了します。
    JavaのJDBCを使っているなら、addBatch等で、一度にたくさんのSQL文を実行できます。また、Statementを使うよりもPrepareStatementを使う方が当然高速です。
    最後にINSERTするときはインデックスをDROPしておいて、集計する段階になってINDEXを作ることでも高速になるでしょう。
  • id:hebe
    Re:案2をお勧めしない理由

    補足ありがとうございます。
    SQL 文については XML から動的に組み立てるライブラリを用意するつもりなのでそう問題ないと思います。
    とすると挙げて頂いた方法も選択肢に入ってきますね。
    どうせ利用頻度も少なそうなので一度それでやってみるのも良いかも…

    ありがとうございます。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません