1

我正在对现有数据库进行升级,该数据库的设计没有任何代码来实现正在考虑的设计。现在我在用代码实现数据库设计方面遇到了障碍。我确定这是否是数据库设计的问题,或者我只是没有看到关于如何做的正确解决方案。

基本逻辑规定如下:

  1. 用户通过席位访问在线培训。用户可以拥有多个席位。
  2. 席位由公司购买,并与产品具有多对多关系。
  3. 产品与模块具有多对多关系。
  4. 模块与课程具有多对多关系。
  5. 课程是最终用户进行培训的访问权限。
  6. 为了搅浑水,出于某种原因,一些用户有多个包含相同产品的席位。
  7. 认证是基于每个产品进行的,而不是基于每个席位。
  8. 用户与存储其当前状态或课程分数的课程具有多对多关系。
  9. 用户在完成该产品的所有模块中的所有课程后,即可对产品进行认证。
  10. 了解用户何时完成特定模块的所有课程也很重要。
  11. 一些席位将用于重新认证,这意味着之前通过产品认证的用户可以注册并参加重新认证考试。
  12. 由于规则 11,用户可以并且将会拥有多个认证记录。
  13. 编辑:当用户完成课程(得分高于 80%)时,用户已(根据当前业务逻辑)完成了所有产品和包含课程的所有席位的课程。

正如我或多或少所描述的那样,我在当前设计和业务逻辑上一直遇到的问题是,我无法找到一种方法来有效地将用户是否已获得特定产品和席位的认证与他们何时获得认证没有。我一直在尝试确定哪些产品下的哪些座位已获得用户认证,哪些没有。部分问题是因为如果他们目前在不同席位下注册了多个相同产品,那么我只需要计算一次产品。

下面是所涉及的架构部分的副本。任何有关如何改进设计或在代码中绘制关联的建议将不胜感激。万一这很重要,这个网站是建立在 LAMPP 堆栈上的。

您可以在此处查看数据库架构的相关部分:http://lpsoftware.com/problem_db_structure.png

4

4 回答 4

2

你要找的是关系除法 ,不是直接用SQL实现的,但是可以做到。在 google 上搜索其他示例。

于 2008-10-02T17:26:28.790 回答
0

快速查看架构后,我认为您可以做的一件事是创建一个“to_be_certified”表。将产品分配给座位时(填充 product_seat_rtab 时)使用 user_id、product_id 和 seat_id 填充它。

在向certificate_rtab 表添加记录时,删除“to_be_certified”表中的相应记录。这将使您可以轻松访问所有经过用户认证和未经过认证的产品。

要消除重复的 product_id,您可以按 product_id 分组。

于 2008-10-02T17:40:06.653 回答
0

您需要对 coursestatus_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 回答
0

更新:

我已经进一步考虑了这个问题,并考虑过简单地删除 user_seat_rtab 表,然后使用等效的certificate_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 回答