1

我的问题可能很愚蠢,因为我认为这是一个非常常见的设计问题,我想有一个简单而常用的解决方案:

  • 我有一张桌子 Producer 和一张桌子 Movie
  • 一位制片人制作了许多电影
  • 一位制片人在他制作的电影中拥有一部最喜欢的电影

我如何在 MySQL 中实现它?

  1. Producer 和 Movie 之间只有一个 ONE-TO-MANY 关系,加上 Movie 表中的“favorite”布尔属性
  2. 一个一对多关系表示“已生产”关系,一个一对一关系表示“最喜欢”关系

第一个方案对我来说似乎更自然,但是当制片人想要改变他最喜欢的电影时,我想第二个方案更有效。使用解决方案 #2 找到制片人最喜欢的电影应该更有效。

我错过了什么?有没有最好的解决方案?如果不是,在哪种情况下我应该使用解决方案 #1 和解决方案 #2?

(当然,我的问题比上面的例子要复杂一些......)

4

6 回答 6

1

(1) 以声明方式执行并不容易/有效。另外,您最终会在所有不喜欢的电影上浪费空间。

(2)是要走的路。不幸的是,这种循环依赖会导致先有鸡还是先有蛋的问题,解决了:

  • 通过推迟其中一个 FK(如果 DBMS 支持它,不幸的是 MySQL 不支持它),
  • 或者通过将 FK 保留在用户 NULL-able 中,这不太理想,因为用户现在可以拥有零或一部喜欢的电影(而不是严格来说是一部)。

假设您希望同一部电影与多个用户相关(使其成为多对多关系,而不是您所说的一对多),您的模型最终会在支持可延迟 FK 的 DBMS 中看起来像这样:

在此处输入图像描述

但是你没有延迟 MySQL 中的约束的奢侈,所以你将被迫做这样的事情:

在此处输入图像描述

CHECK (FAVORITE_USER_ID IS NULL OR FAVORITE_USER_ID = USER_ID)
于 2012-11-05T20:20:59.850 回答
1

一般来说,我会选择解决方案 2。除了更简单地查询最喜欢的电影之外,这还有一个内置约束的额外好处,将用户限制为只有一部喜欢的电影。此外,这会稍微小一些,每个用户有一个 id,而不是每个观看电影用户有一个布尔值。然而,一个副作用是您可以在不观看的情况下收藏一部电影。

仅当您希望将来扩展收藏夹系统以包含多个收藏夹时,解决方案 1 才是首选。然而,这显然是不可取的。


值得一提的是,用户和电影之间的关系是多对多,而不是一对多,因为每个用户都有自己的观看电影列表。因此,您将需要第三个表来链接两者。当然,除非您只是为每个用户提供一个不相关字符串的列表,但我怀疑情况是否如此。

于 2012-11-05T15:28:57.507 回答
1

布尔属性不仅占用更多空间,而且看起来会阻止多个用户拥有一个收藏夹。

第二种解决方案听起来是正确的。在 User 中有一个字段来表示每个用户的最爱,还有一个附加表来建立一对多的“已观看”关系。

如果您需要确保用户确实看过他/她最喜欢的电影,您应该将该逻辑作为业务规则添加到您的数据访问对象中。

于 2012-11-05T15:25:27.300 回答
0

如果您确定总是只有一部电影,我将在用户表中具有“最喜欢的电影 ID”属性,以及用户和电影之间的多对多关系(许多用户可以观看同一部电影)

因此,总共三个表,用户表中的标志。

于 2012-11-05T15:22:51.443 回答
0

我认为第二种解决方案更可行。您可以为这些关系创建两个表,一个名为 HasWatched,另一个名为 Favorite。这两个表都包含两列,名为 userId - movieId。Haswatched 表的主键是 (userId - movieId) 元组。但是Favorite 表的主键只有userId。因此,您可以应用所有约束。

于 2012-11-05T15:24:40.057 回答
0

我会做第三张桌子......我不认为是一对多关系,它是多对多,一个用户可以观看很多电影,但一部电影可以被很多用户观看......

我会使用 user_id、movie_id 制作一个用户表、一个电影表和一个用户观看电影的表,并添加一个指向用户喜爱的 movie_id 的 favorite_movie 字段。

于 2012-11-05T15:27:11.067 回答