次のデザインを使用してサイトのテーブルを作成しています
デザイン1
デザイン 2
登録したすべてのユーザーが挑戦するわけではないため、デザイン 1が適しています。3 番目のテーブルに挿入すると、それに応じてテーブル 2 のスコアが更新されます。しかし、user_id フィールドは冗長になります。
デザイン 2 では、まだ正規化されていないすべてのユーザーに 0 または NULL 値が設定されます。最適な設計はどのようなもので、正規化や組織の鍵はどの程度重要ですか?
次のデザインを使用してサイトのテーブルを作成しています
デザイン1
デザイン 2
登録したすべてのユーザーが挑戦するわけではないため、デザイン 1が適しています。3 番目のテーブルに挿入すると、それに応じてテーブル 2 のスコアが更新されます。しかし、user_id フィールドは冗長になります。
デザイン 2 では、まだ正規化されていないすべてのユーザーに 0 または NULL 値が設定されます。最適な設計はどのようなもので、正規化や組織の鍵はどの程度重要ですか?
編集:
将来の人のために-OPが何を求めているのかを理解するのに問題があったので、少し迷ったらコメントを読んでください。最終的に、彼らは集計データを保存しようとしていましたが、それをどこに置くべきか、またそれを実現する方法を知りませんでした。解決策は基本的に、この投稿の最後で説明されている挿入トリガーを使用することです。
user
の累積合計を格納するために、テーブルに別の列を追加することにしましたuser_problem.score
。ただし、正規化を過度に使用しているように見えても、新しいテーブル (列user_id
と をtotal_sum
含む) を作成することはまったく悪いオプションではありません。頻繁に更新されるデータと、めったに変更されないデータを分けておくとよい場合があります。そうすれば、何か問題が発生した場合でも、静的データが安全であることがわかります。
私が触れたことのない他のものは、一般的に集計データの保存に関連する データの同時実行性と整合性の問題です...そのため、注意してください。
私は次のようなことを提案します:
User Table
User_ID - Email - Name - Password - FB_ID
-- holds all the user information
Problem Table
Problem_ID - Problem_Title - Problem_Descr
-- holds all the info on the individual challenges/problems/whatever
User_Problem Table
User_Problem_ID - User_ID - Problem_ID - Score - Completion_Date
-- Joins the User and Problem tables and has information specific
-- to a user+challenge pair
これは、ユーザーが多くの課題/問題に対処できることを前提としています。また、1 つの問題/課題を複数のユーザーが引き受けることができます。
特定のユーザーによるすべての問題を表示するには、次のようにします。
select user.user_id,
user.name,
problem_title,
problem_descr,
user_problem.score,
user_problem.completed_date
from user
join user_problem on user.user_id = user_problem.user_id
join problem on user_problem.problem_id = problem.problem_id
where user.user_id = 123 or user.email = 'stuff@gmail.com'
フィールドの長さvarchar
はかなり一般的です...
create table User(
User_ID int unsigned auto_increment primary key,
Email varchar(100),
Name varchar(100),
Password varchar(100),
FB_ID int
);
create table Problem (
Problem_ID int unsigned auto_increment primary key,
Problem_Title varchar(100),
Problem_Descr varchar(500)
);
create table User_Problem (
User_Problem_ID int unsigned auto_increment primary key,
User_ID int unsigned,
Problem_ID int unsigned,
Score int,
Completion_Date datetime,
foreign key (User_ID) references User (User_ID),
foreign key (Problem_ID) references Problem (Problem_ID)
);
コメントの下からの会話の後...ユーザーに列を追加します。
User Table
User_ID - Email - Name - Password - FB_ID - Total_Score
列にデフォルト値の 0 を指定したのは、その人に関連する問題や課題がなければ、それを望んでいる/必要としているように思われたからです。他のものにもよりunsigned
ますが、負のスコアが決してないというルールがある場合は、これを int にすることが有益な場合があります。
alter table user add column Total_Score int default 0;
次に...user_problem
テーブルに影響を与えるテーブルで挿入トリガーを使用しuser
ます。
CREATE TRIGGER tgr_update_total_score
AFTER INSERT ON User_Problem
FOR EACH ROW
UPDATE User
SET Total_score = Total_score + New.Score
WHERE User_ID = NEW.User_ID;
したがって... 行が に追加された後User_Problem
、新しいスコアをuser.total_score
...に追加します。
mysql> select * from user;
+---------+-------+------+----------+-------+-------------+
| User_ID | Email | Name | Password | FB_ID | Total_Score |
+---------+-------+------+----------+-------+-------------+
| 1 | NULL | kim | NULL | NULL | 0 |
| 2 | NULL | kyle | NULL | NULL | 0 |
+---------+-------+------+----------+-------+-------------+
2 rows in set (0.00 sec)
mysql> insert into user_problem values (null,1,1,10,now());
Query OK, 1 row affected (0.16 sec)
mysql> select * from user;
+---------+-------+------+----------+-------+-------------+
| User_ID | Email | Name | Password | FB_ID | Total_Score |
+---------+-------+------+----------+-------+-------------+
| 1 | NULL | kim | NULL | NULL | 10 |
| 2 | NULL | kyle | NULL | NULL | 0 |
+---------+-------+------+----------+-------+-------------+
2 rows in set (0.00 sec)
mysql> select * from user_problem;
+-----------------+---------+------------+-------+---------------------+
| User_Problem_ID | User_ID | Problem_ID | Score | Completion_Date |
+-----------------+---------+------------+-------+---------------------+
| 1 | 1 | 1 | 10 | 2013-11-03 11:31:53 |
+-----------------+---------+------------+-------+---------------------+
1 row in set (0.00 sec)