1

検討中の設計を実装するためのコードを一切使用せずに設計された既存のデータベースのアップグレードに取り組んでいます。今、私はデータベース設計をコードで実装するという点で壁にぶつかりました。データベースの設計に問題があるのか​​、それとも、何をする必要があるのか​​について正しい解決策が見当たらないだけなのかどうかは確かです。

基本的なロジックでは、次のように規定されています。

  1. ユーザーは、シートを介してオンライントレーニングにアクセスします。ユーザーは複数のシートを持つことができます。
  2. シートは企業によって購入され、製品と多対多の関係があります。
  3. 製品は、モジュールと多対多の関係にあります。
  4. モジュールは、レッスンと多対多の関係にあります。
  5. レッスンは、エンドユーザーがトレーニングのためにアクセスするものです。
  6. 水を濁らせるために、何らかの理由で、一部のユーザーは同じ製品を含む複数のシートを持っています。
  7. 認定は、シートごとではなく、製品ごとに行われます。
  8. ユーザーは、レッスンの現在のステータスまたはスコアを保存するレッスンと多対多の関係を持っています。
  9. ユーザーは、製品のすべてのモジュールのすべてのレッスンを完了すると、製品の認定を受けます。
  10. 特定のモジュールのすべてのレッスンがユーザーによっていつ完了するかを知ることも重要です。
  11. 一部のシートは再認定用になります。つまり、以前に製品の認定を受けたユーザーは、サインアップして再認定試験を受けることができます。
  12. ルール11により、ユーザーは複数の認証レコードを持つことができます。
  13. 編集:ユーザーがレッスンを完了すると(スコアが80%を超える)、ユーザーは(現在のビジネスロジックに従って)レッスンを含むすべての製品とすべてのシートのレッスンを完了します。

私が多かれ少なかれ説明したように、現在の設計とビジネスロジックで遭遇し続ける問題は、ユーザーが特定の製品とシートの認定を受けているかどうかと、それらがいつ認定されているかを効果的に結び付ける方法が見つからないことです。してない。私は、どのシートがユーザーに対して認定されているか、どの製品が認定されていないかを確認しようと、ひっかかりを続けています。問題の一部は、それらが現在異なるシートの下で同じ製品の複数に登録されている場合、製品を1回だけカウントする必要があるためです。

以下は、関連するスキーマの部分のコピーです。デザインを改善する方法やコードで関連付けを描画する方法についての提案をいただければ幸いです。重要な場合、このサイトはLAMPPスタック上に構築されています。

ここでデータベーススキーマの関連部分を表示できます。http://lpsoftware.com/problem_db_structure.png

4

4 に答える 4

2

あなたが探しているのは、リレーショナル除算です 。SQL に直接実装されていませんが、実行できます。グーグルで他の例を検索してください。

于 2008-10-02T17:26:28.790 に答える
0

アップデート:

私はこの問題をさらに検討し、単純に user_seat_rtab テーブルを削除してから、同等の Certification_rtab テーブル (おそらく名前を変更したもの) を使用して、ユーザーの座席のステータスに関するすべての情報を保持する方がうまくいくかどうかを検討しました。このようにして、ユーザー、ユーザーのシート、シート内の各製品、およびユーザーが特定の製品とシートを認定しているかどうかの間に直接的な関係が確立されます。

したがって、質問とともに投稿されたスキーマに次の変更を適用します。

DROP TABLE user_seat_rtab;
RENAME TABLE certification_rtab TO something_different;

この新しい構造をさらに正規化する別の方法は、次のようにすることです。

ALTER TABLE user_seat_rtab 
    DROP PRIMARY KEY;
    ADD COLUMN product_id int(10) unsigned NOT NULL;
    ADD CONSTRAINT pk_user_seat_product PRIMARY KEY (user_id, seat_id, product_id);
    ADD CONSTRAINT fk_product_user_seat FOREIGN KEY (product_id) REFERENCES product_rtab(id) ON DELETE RESTRICT;

これで問題が解決するのか、それとも新しい問題を導入する際に問題の性質がわずかに変わるだけなのか、私にはよくわかりません。それで、誰か他の批判や提案はありますか?

于 2008-10-03T13:32:43.740 に答える
0

スキーマをざっと見てみると、できることの 1 つは「to_be_certified」テーブルを作成することだと思います。製品がシートに割り当てられたとき (product_seat_rtab が入力されたとき)、user_id、product_id、および seat_id を入力します。

Certification_rtab テーブルにレコードを追加したら、「to_be_certified」テーブルの対応するレコードを削除します。これにより、ユーザーに対して認定されているすべての製品とそうでない製品に簡単にアクセスできます。

重複する product_id を取り除くには、product_id でグループ化できます。

于 2008-10-02T17:40:06.653 に答える
0

lessonstatus_rtab テーブルに変更を加える必要があります。

CREATE TABLE lessonstatus_rtab (
  user_id    INT NOT NULL,
  seat_id    INT NOT NULL,
  lesson_id  INT NOT NULL REFERENCES lesson_rtab,
  accessdate TIMESTAMP,
  score      NUMERIC(5,2) NOT NULL DEFAULT 0,
  PRIMARY KEY (user_id, seat_id, lesson_id),
  FOREIGN KEY (user_id, seat_id) REFERENCES user_seat_rtab (user_id, seat_id)
);

次に、ユーザーがシートを持っている各製品についてクエリを実行できます。彼は認定されていますか? これは、彼が獲得し​​たレッスンの数 (たとえば 50% 以上) が、製品のすべてのモジュールのレッスンの数と同じであると想定しています。

SELECT p.name, us.user_id, us.seat_id, COUNT(l.id) = COUNT(lu.lesson_id) AS is_certified
FROM user_seat_rtab AS us
 JOIN seat_rtab AS s ON (s.id = us.seat_id)
 JOIN product_seat_rtab AS ps ON (ps.seat_id = s.id)
 JOIN product_rtab AS p ON (p.id = ps.product_id)
 JOIN product_module_rtab AS pm ON (pm.product_id = p.id)
 JOIN module_rtab AS m ON (m.id = pm.module_id)
 JOIN module_lesson_rtab AS ml ON (ml.module_id = m.id)
 JOIN lesson_rtab AS l ON (l.id = ml.lesson_id)
 LEFT OUTER JOIN lessonstatus_rtab AS lu 
   ON (lu.lesson_id = l.id AND lu.user_id = us.user_id 
     AND lu.seat_id = us.seat_id AND lu.score > 0.50)
GROUP BY p.id, us.user_id, us.seat_id;
于 2008-10-02T18:29:21.137 に答える