0

次のデザインを使用してサイトのテーブルを作成しています

デザイン1

ここに画像の説明を入力

デザイン 2

ここに画像の説明を入力

登録したすべてのユーザーが挑戦するわけではないため、デザイン 1が適しています。3 番目のテーブルに挿入すると、それに応じてテーブル 2 のスコアが更新されます。しかし、user_id フィールドは冗長になります。

デザイン 2 では、まだ正規化されていないすべてのユーザーに 0 または NULL 値が設定されます。最適な設計はどのようなもので、正規化や組織の鍵はどの程度重要ですか?

4

1 に答える 1

2

編集

将来の人のために-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)
于 2013-11-03T16:59:06.560 に答える