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

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

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

1回答

473閲覧

「掲示板」と「記事」の閲覧履歴の保存にあたって、同じテーブルにすべきか否か

nikuatsu

総合スコア177

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

1グッド

0クリップ

投稿2022/09/06 09:23

編集2022/09/06 09:32

前提

MySQLとphpで簡単な掲示板サイトを作る中で、閲覧履歴の保存に取り組んでいます。

実現したいこと

「掲示板」と「記事」というコンテンツがあるのですが、「掲示板の閲覧履歴」と「記事の閲覧履歴」を同じテーブルにすべきか否か、その判断基準を知りたいです。

発生している問題

以下2パターン考えましたが、「どちらが、どういうときに良いのか?」判断できません…。

【パターン1】同じテーブルにする
【パターン2】別のテーブルにする

基本テーブル

まず基本的には次の「ユーザー、掲示板、記事」の3つがあります。

SQL

1CREATE TABLE tbl_users ( 2 `ID` INT(10) PRIMARY KEY AUTO_INCREMENT, 3 `name` VARCHAR(100) 4); 5CREATE TABLE tbl_threads ( 6 `ID` INT(10) PRIMARY KEY AUTO_INCREMENT, 7 `title` VARCHAR(100), 8 `user_ID` INT(10), 9 CONSTRAINT fk_threads_01 FOREIGN KEY (`user_ID`) REFERENCES tbl_users (`ID`) 10); 11CREATE TABLE tbl_posts ( 12 `ID` INT(10) PRIMARY KEY AUTO_INCREMENT, 13 `title` VARCHAR(100), 14 `content` VARCHAR(1000), 15 `user_ID` INT(10), 16 CONSTRAINT fk_posts_01 FOREIGN KEY (`user_ID`) REFERENCES tbl_users (`ID`) 17);

閲覧履歴テーブル

以下に問題の2パターンを記載します。
count_visitedsカラムはDUPLICATE KEY UPDATEでカウントアップする意図です。

【パターン1】同じテーブルにする

まず閲覧履歴を同じテーブルに保存するならこうだと思います。

SQL

1CREATE TABLE tbl_visiteds ( 2 `post_ID` INT(10), 3 `thread_ID` INT(10), 4 `user_ID` INT(10), 5 `count_visiteds` INT(10), 6 UNIQUE u_visiteds_01 (`post_ID`, `thread_ID`, `user_ID`), 7 CONSTRAINT fk_visiteds_01 FOREIGN KEY (`post_ID`) REFERENCES tbl_posts (`ID`), 8 CONSTRAINT fk_visiteds_02 FOREIGN KEY (`thread_ID`) REFERENCES tbl_threads (`ID`), 9 CONSTRAINT fk_visiteds_03 FOREIGN KEY (`user_ID`) REFERENCES tbl_users (`ID`) 10);
【パターン2】別のテーブルにする

または別のテーブルだとこうだと思います。

sql

1CREATE TABLE tbl_visited_posts ( 2 `post_ID` INT(10), 3 `user_ID` INT(10), 4 `count_visiteds` INT(10), 5 UNIQUE u_visited_posts_01 (`post_ID`, `user_ID`), 6 CONSTRAINT fk_visited_posts_01 FOREIGN KEY (`post_ID`) REFERENCES tbl_posts (`ID`), 7 CONSTRAINT fk_visited_posts_02 FOREIGN KEY (`user_ID`) REFERENCES tbl_users (`ID`) 8); 9CREATE TABLE tbl_visited_threads ( 10 `thread_ID` INT(10), 11 `user_ID` INT(10), 12 `count_visiteds` INT(10), 13 UNIQUE u_visited_threads_01 (`thread_ID`, `user_ID`), 14 CONSTRAINT fk_visited_threads_01 FOREIGN KEY (`thread_ID`) REFERENCES tbl_threads (`ID`), 15 CONSTRAINT fk_visited_threads_02 FOREIGN KEY (`user_ID`) REFERENCES tbl_users (`ID`) 16);

自分の考え

まず同じテーブルの場合、記事を閲覧した際はthread_IDカラムにNULLを、掲示板を閲覧した際はposts_IDカラムにNULLを入れざるを得ないかと思います。つまり必ず一方のカラムがNULLになり、この点どうなのかと疑問です。

または別のテーブルの場合、「コンテンツの数だけ閲覧履歴テーブルが増える」ということにやや違和感を覚えます。さらにINSERTのクエリを2回実行しなければならない点も疑問です。

以上のように、「どちらが、どういうときに良いのか?」判断できません…。
「そっちのパターンだとこういうときに困る」「もっと別のパターンが良い」など先人の皆様からアドバイスを頂戴できましたら幸いです。

バージョン

PHP 8.0
MySQL 5.7.31
phpMyAdmin 4.4.15.10

宜しくお願いいたします。

kemusi👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

掲示板と記事のテーブルが分かれている=両者を完全に別物として扱っている
のであれば、
掲示板の閲覧履歴記事の閲覧履歴
も名前が似ているだけで別の役割を持つデータであると考えるのが自然かと思います。

そのため、同じテーブルにしたい積極的理由が無い限りは、別のテーブルにしておく方が自然かつ楽だと思いますよ。

投稿2022/09/06 13:35

tanat

総合スコア18713

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nikuatsu

2022/09/07 13:04

積極的理由というとどんなものが当たるでしょうか。 私はまず「閲覧履歴という同じようなデータだから」という積極的理由を考えておりましたが、 > 名前が似ているだけで別の役割を持つデータであると考えるのが自然 とのアドバイスのおかげで、どうやらこれは積極的理由としてふさわしくないのだと理解できました。 しかし、次の2点の積極的理由もございます。 > 「コンテンツの数だけ閲覧履歴テーブルが増える」ということにやや違和感を覚えます。 > さらにINSERTのクエリを2回実行しなければならない点も疑問です。 おそらくこの2点も積極的理由としてふさわしくないのでしょうが、それがなぜかはわかりません。 そこで、この2点によって同じテーブルにすべきでないのはなぜか?もしくは逆に、積極的理由としてふさわしいものは何か?を知りたく思っています。このあたりもう少し詳しく教えて頂けませんでしょうか。
tanat

2022/09/07 16:17

[回答補足] > 積極的理由というとどんなものが当たるでしょうか。 DB設計者が「設計ポリシーと要件を踏まえたうえで、他の方法より優れている/必須だと思えば」それは積極的な理由です。 *要件が存在しなかったり緩かったりする場合は、そもそも設計の妥当性は測れないので、積極性も同じくらい緩い判断基準にしかなりません。 > 私はまず「閲覧履歴という同じようなデータだから」という積極的理由を考えておりましたが、 であればそれが「積極的理由」で問題無いと思いますよ。 (これは嫌味などではなく、字面そのままの意味です) それを前提として、回答者としては積極的な理由があるように見えなかった理由を補足すると > 掲示板と記事のテーブルが分かれている=両者を完全に別物として扱っている > のであれば、 > 名前が似ているだけで別の役割を持つデータであると考えるのが自然 この3行はセットで > 私はまず「閲覧履歴という同じようなデータだから」という積極的理由を考えておりましたが、 というのは、 「では記事テーブルと掲示板テーブルも同じでいいのでは?どの辺まで同じでどの辺から違うものと判断しているのか?」 と思ったので、(私の主観では)積極的な理由ではないのかな?と感じての回答です。 >> 「コンテンツの数だけ閲覧履歴テーブルが増える」ということにやや違和感を覚えます。 については、(今の方向性で同じテーブルにすると)「コンテンツの数(種類)が増えたらカラムが増える、コンテンツの数(種類)が減ったらカラムが減ったり死にカラムが生まれる」のは確実に大変なので、 「やや違和感を覚える」くらいの理由であれば避けることをお勧めします。 >> さらにINSERTのクエリを2回実行しなければならない点も疑問です。 これは何が疑問なんでしょうね? この違和感を突き詰めちゃうと、「山ほどカラムのあるテーブルを一つ用意してすべて一回のINSERTで済ませよう」みたいな設計思想になっちゃいませんか? 「なんとなくINSERTは少ない方がいいと思っている」くらいの疑問であれば 「別にそんなことは無いですよ。リレーショナルデータベースである限り、複数テーブル連携を前提としたデータ操作は当然にあるものです」くらいの粒度での回答になります。 [追加] > 「そっちのパターンだとこういうときに困る」「もっと別のパターンが良い」など先人の皆様からアドバイスを頂戴できましたら幸いです については、 要件が学習用の掲示板くらいなら別にどっちでも問題なさそうなので、出来る方法で実装した後に実際に使ってみて課題/問題を考える方が建設的でしょう としか言えません。 設計の妥当性評価は要件をどれだけ満たしているかとイコールなので、 要件が曖昧だと評価も曖昧なラインでしかできません。 (よほどアウトな場合を除いては要件を無視して絶対的な評価を行うのは不可能なのです。) まずは、現状で色々曖昧になっているであろう(質問には記載されていないだけであるのかもしれませんが)要件を可能な限り細かく考えてみてから、それをクリアできるか考えてみてください。 例えば、 コンテンツの種類は増減するのか、 増減するならどれくらいの種類まで増えるのか、 データ数どの程度を想定していて、 パフォーマンス要件はどの程度なのか、 その他の機能追加の可能性はどの程度あるのか、 運用中にデータを編集する必要があったりするのか? 検索はどのように行うのか? 等々、 DB設計を行うにあたって先に決まって無いといけないことがいくらでもあります。 DBはアプリケーションを実装するためのパーツの一つなので、 アプリケーションそのものの詳細仕様(運用まで含めた詳細仕様)を設計する ↓ DB設計に落とし込む ↓ 無理が出たらアプリケーションの仕様を直すかDB側で無理をするかを決めて設計に落とし込む という感じで、設計してみて具体的に困るところが見えたら再度質問をすると、より具体的な回答が得られるかと。 現状のなんとなくの違和感の払拭や、いろいろなパターンを先に知りたいんだという事であれば 定番の書籍でDB設計とアンチパターンを学習されることをお勧めします。
nikuatsu

2022/09/07 17:05

[回答補足] について > それを前提として、回答者としては積極的な理由があるように見えなかった理由を補足すると... >「やや違和感を覚える」くらいの理由であれば... >「なんとなくINSERTは少ない方がいいと思っている」くらいの疑問であれば... すごいです。こちらの意図と心情を汲み取った上で、その前提に基づいて、視点と抽象性を的確に操作した丁寧なご返答だと思います。文意を読むこと、教えることにものすごく長けた方で驚きました。 [追加] について 設計の妥当性評価のための要件ですが、まさに具体的要件がわからないレベルでした。 しかしその例示をたくさん頂き今度の検討の指針となりました。 大変勉強になりました。深く感謝申し上げます。
tanat

2022/09/07 17:36

お役に立てたようでよかったです。 自分が初学者の時に要件を意識できていたかというとそんなことは全く無いですが、最初から言葉や概念だけでも知ってれば結構違うとは思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問