質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.04%

アンケートアプリを作成中。DB設計で躓いてしまいました。。。

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 346

west_side_park

score 12

前提・実現したいこと

Railsで、学生たちに国語・数学・理科・社会・英語の習熟度をラジオボタンを使って0~5段階でチェックしてもらうアプリを作成しようとしています。

躓いていること

DB設計で躓いてしまい、お力をお借りしたいです。
今回、例えば数学であれば、

イメージ説明

このように、大項目の下に中項目、中項目の下に小項目、というような形式です。
これが残り4教科分あります。
加えて、最後にアンケート欄を設けます。

考えてみたテーブル設計

■ Userテーブル
name:string
password:string
あとadminなど追加、、、

■ Questionテーブル
user_id:integer ← 誰の回答なのかを管理するため
description:text ← 冒頭の説明文

■ FirstClassテーブル(大項目)
first_title:text ← 大項目の名称(数学)

■ SecondClassテーブル(中項目)
second_title ← 中項目の名称(数Ⅰ、数A)
first_class_id:integer ← どの大項目に属するかを管理するため

■ ThirdClassテーブル(小項目)
third_title ← 小項目の名称(順列)
first_class_id:integer ← どの大項目に属するかを管理するため
second_class_id:integer ← どの中項目に属するかを管理するため

■ ForthClassテーブル(少々項目)
forth_title ← 小項目の名称(円順列、重複順列)
first_class_id:integer ← どの大項目に属するかを管理するため
second_class_id:integer ← どの中項目に属するかを管理するため
third_class_id:integer ← どの小項目に属するかを管理するため

■ Answerテーブル
user_id:integer ← 誰のアンケートなのかを管理するため
first_class_id:integer ← どの大項目に属するかを管理するため
second_class_id:integer ← どの中項目に属するかを管理するため
third_class_id:integer ← どの小項目に属するかを管理するため
forth_class_id:integer ← どの少々項目に属するかを管理するため
coice_number:integer ← 回答番号

今回のような少し複雑な表をデータベースにするとき、このような考え方で合っていますでしょうか??

初歩的な質問かもしれませんが、どうぞよろしくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

質問文にある表の形をそのまま DB にするので十分では?

User テーブル
 id, name, password, ...

Category テーブル
 id, 教科名, 項目名1, 項目名2, 項目名3, 項目名4, 項目名5

Answer テーブル
 id, user_id, category_id, 回答

Category テーブ中の文字列の重複記載が気になるなら、

名前 テーブル
  id, 名前


として、Caeroby てテーブルに 名前_id を記載するようにすればよいです。

親子関係のリンクをレコードに持つ方法は柔軟性はありますが、質問文にあるような形式の表示を組み立てようとする際に苦労する気がします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/25 09:47

    今回は、表示の仕方を項目順で考えていてeach文で取り出すにしても難しいなぁ、、、と悩んでいたので、Katoy様のご指摘でかなりイメージができてきました!テーブルの数自体はそんなに多くないので、一旦これで実装に入りつつ、不都合があればその時に設計を考え直してみます。
    私は私立中学の教師なのですが、情報系の大学を出たというだけでなぜか急に、生徒が使うこのアプリを作るように命じられ焦っておりました…
    一応期限が5月中旬なのでGWも使えば何とかと思っていますが、また煮詰まった時にぜひ相談させてください。ありがとうございました!

    キャンセル

  • 2019/04/25 21:13

    > ... 情報系の大学 ... 期限が5月中旬 ...
    無謀な指示としかおもえません、生徒の親・兄弟でにプログラミングができるかたがいれば、そのかたに対価を払ってつくってもらったほうがよいのでは?

    キャンセル

  • 2019/05/01 14:20

    新しい教頭が意識だけ高い系みたいな感じでして、生徒がプログラミングに興味を持つキッカケにもなりますからお願いしますってことでした…。もう職員の間で決定事項のような感じだったらしく、断るすきもなく引き受けてしまいました。しっかり断ればよかったのですが、受けてしまった以上、やるしかないって感じです。。。

    キャンセル

+1

DBの設計について一番単純なデータ保持の仕方は
「隣接リストモデル」すなわち、自分のIDを持ち、自分の親のIDを持つ方法

create table tbl(id int primary key,pid int null,name varchar(20),endflg tinyint);
insert into tbl values
( 1,null,'数学',0),
( 2, 1,'数IA',0),
( 3, 2,'数I',0),
( 4, 3,'数と列',1),
( 5, 3,'論理と集合',1),
( 6, 3,'2次関数',1),
( 7, 2,'数A',0),
( 8, 7,'場合の数と確率',1),
( 9, 7,'順列',0),
(10, 9,'円順列',1),
(11, 9,'重複順列',1),
(12, 1,'数IIB',0),
(13,12,'数II',0),
(14,13,'式と証明',1),
(15,13,'複素数と方程式',1),
(16,13,'図形と方程式',1),
(17,12,'数B',0),
(18,17,'平面ベクトル',1),
(19,17,'空間ベクトル',1);


endflgは最終データかどうか(別になくてもよい)

  • データ検出
select * from tbl as t1
left join tbl as t2 on t1.id=t2.pid
left join tbl as t3 on t2.id=t3.pid
left join tbl as t4 on t3.id=t4.pid
left join tbl as t5 on t4.id=t5.pid
where t1.pid is null
order by t1.id,t2.id,t3.id,t4.id,t5.id


※この場合データの保持が冗長なため
ネストが最大いくつになるかをわかっていないと調べられません。

これを更に効率よく管理するには「入れ子集合モデル」という
データ保持の仕方が必要です。
このモデルの場合、データがインタラクティブに変化していくため
プロシージャという仕組みで随時データを書き換える必要がでてきますので
もし興味があるようなら聞いてください

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/23 22:32

    ご回答ありがとうございます。プロシージャという単語は初めて聞きました。SQLもまだ全然なレベルなので時間がかかるかもしれませんが、丁寧にご回答いただいたのでしっかり調べたいと思います。

    キャンセル

+1

「Aさんの重複順列が2点」
という情報がわかれば
「重複順列は順列に属する」
「順列は数Aに属する」
「数Aは数IAに属する」
「数IAは数学に属する」
と遡れますよね。
質問のケースでは一つ一つのテーブルが自分の親を参照するだけで十分なはずです。

仮に質問に記載されているように一番下の項目がすべての上位項目に対して「どこに属するか」と指定を入れた場合、「重複順列は数IAに属し、英語に属する」かつ「数IAは数学に属する」という矛盾が発生してしまう可能性を含んでしまい、データの整合性が担保できなくなってしまいます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/24 00:37

    数学 -> 数1A -> 数A -> 順列 -> 円順列 -> Aさんが2点
    に対して
    数学 -> 数1A -> 数1 -> 数と列 -> 数と列 -> Aさんが2点
    とみなせば同じ階層の数で表現できますよね?

    キャンセル

  • 2019/04/24 00:42

    ちなみに、「Aさんが2点」と言っても2つの値の意味(「数と列」、「円順列」の点数)は違うのでデータベース上は親IDが違って同じレコードにはなりませんし、
    同じ「数と列」であっても、違う階層を表現しているものなのでデータベース上はテーブルが分かれるため同じものではありません。

    キャンセル

  • 2019/04/24 15:29

    「数と列」と「円順列」を同じ階層で考えるということの意味が分かりました。個人的に、親子で名前が同じになるケースを考えるとややこしく感じるので、以下のテーブル設計で進めてみようと思います。

    Category(項目)テーブル
    id, 教科名, 項目名1, 項目名2, 項目名3, 項目名4, 項目名5
    ⇒(項目名3, 項目名4, 項目名5はnullの場合もある)
    Answer テーブル
    id, user_id, category_id, 回答

    非常に分かりやすい指摘をいただきましてありがとうございます!
    また考えが詰まったとき、ご助力いただけますと嬉しいです。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる