我整理了一个简单的数据库,用于存储有关奖项和提名的信息。我试图尽可能多地删除数据冗余。以下是它目前的看法:
提名表的原因是我意识到一个提名会有很多被提名者。例如,奖励Best Screenplay
可以转到Ken Levine and David Isaacs
或Woody Allen
或Joss Whedon, Andrew Stanton, Joel Cohen and Alec Sokolow
。
注意:Award.name
是奖励的名称,例如: Best Actor
。
感谢您指出任何可能的改进。
答案 0 :(得分:2)
NOMINATED
表在NOMINEES
和NOMINATIONS
之间创建m:n关系。删除其NominatedID
列,并使用两列NomineeID
和NominationID
作为主键。这可以防止同一人在同一提名中被提名两次。
NOMINEES NOMINATED
+---------------+ +---------------------+ NOMINATIONS
| PK NomineeID |<----o| PK FK NomineeID | +------------------+
+---------------+ | PK FK NominationID |o--->| PK NominationID |
| Name | +---------------------+ +------------------+
+---------------+ | FK FilmID |
| FK AwardID |
| FK EventID |
+------------------+
答案 1 :(得分:1)
次要说明
我更喜欢表格和列名称的单数形式,因此Nominees
变为Nominee
,Awards
变为Award
等等。
将Award
表重命名为AwardCategory
,以@wildplasser在评论中建议。
主要说明
正如@Olivier指出的那样,m::n
关系中间表(如Nominated
个)将对化合物UNIQUE
产生(NomineeId, NominationId)
约束。因此,最好删除自动生成的(代理)键并使复合键为PRIMARY KEY
。这是关系的natural key,使用它作为主键有几个优点。在这种情况下,surrogate key完全没有任何意义,除了有更宽的行和一个更无用的索引。无论如何,自然键的两部分将用于连接。
同样的事情适用于Nomination
表!复合(FilmId, AwardCategoryId, EventId)
将是UNIQUE
密钥,以确保同一事件的同一奖项类别的电影不会获得2次提名,因此再次删除代理键并使此化合物成为主要内容会更好键。反思,我们可能会为同一部电影的同一奖项类别提名2项提名,比如两个'Best Supporting Actor'
,所以我们在主键中添加NominatioNo
(如果我们想要限制提名,这可以很方便对于某个类别或所有人都说常数5)。
现在,(有趣且有趣的)事情是Nominated
表必须重新检查并具有复合(NomineedId, FilmId, AwardCategoryId, EventId)
主键 - 并且只有这4列作为属性。
我不确定Event
和Ceremony
表到底要存储的是什么,但我们假设Ceremony
表用于存储有关不同仪式的信息(例如'Oscar Awards'
,'Strawberry Awards'
)和Event
表用于存储有关一年仪式的信息(例如('Oscar', 2011), ('Oscar', 2012), ('Starwberry Awards', 2012)
)。因此,我会将Year
移至Event
表,并将(CeremonyId, EventYear)
作为事件的Priamry Key。 (我很可能错了,你更了解你的数据。)。
因此,Nomination.EventId
已被CeremonyId
和EventYear
取代,Nomination
和Nominated
的主要密钥会更长! (这是使用自然键作为主键的一个缺点)。让我们看看到目前为止我们得到了什么:
Database Design 1 http://img594.imageshack.us/img594/9592/oscarw.png
您可以轻松地将NominationWinner
(作为1:1
关系的表格添加到Nomination
)来存储哪个提名赢得了哪个类别((CeremonyId, EventYear, AwardCategoryId)
上的唯一约束将强制执行那)。设计将是这样的:
Database Design 1 http://img845.imageshack.us/img845/2108/oscar3x.png
拥有如此复杂的主键可能看起来很笨拙,但在连接表时会有所帮助。想象一下,你想找到50岁和60岁的“草莓奖”的所有获奖者,并且只为“女演员”类别找到奖项,并展示该奖项的电影。您不必加入所有中间表。相反,您只能使用NominationWinner
,Nominee
,Ceremony
,Film
和AwardCategory
表(并且仅使用Nominated
个中间版来检索数据表):
SELECT ne.Name AS Winner
, wi.EventYear AS Year
, aw.AwardCategoryTitle AS Category
, fm.Title AS FilmTitle
FROM
NominationWinner AS wi
JOIN
Ceremony AS ce
ON ce.CeremonyId = wi.CeremonyId
JOIN
AwardCategory AS aw
ON aw.AwardCategoryId = wi.AwardCategoryId
JOIN
Film AS fm
ON fm.FilmId = wi.FilmId
JOIN
Nominated nd
ON nd.CeremonyId = wi.CeremonyId
AND nd.EventYear = wi.EventYear
AND nd.AwardCategory = wi.AwardCategory
AND nd.NominationNo = wi.NominationNo
AND nd.FilmId = wi.FilmId
JOIN
Nominee AS ne
ON ne.NomineeId = nd.NomineeId
WHERE
ce.CeremonyTitle = 'Strawberry Awards'
AND wi.EventYear BETWEEN 1950 AND 1969
AND aw.AwardCategoryTitle LIKE '%Actress%'