【问题标题】:SQL movie table design & querySQL电影表设计与查询
【发布时间】:2015-03-31 12:55:05
【问题描述】:

首先我应该说我对 SQL 和数据库还很陌生。我读了很多书,并且缩小了我的数据库设计和问题的范围。我现在试着解释一下。

所以我正在尝试构建“典型”电影/电影数据库(用于 SQL 服务器)。

每部电影可以有很多演员,每个演员都可以参演很多电影。 导演和流派也是如此。 (与 dbo.Films 的多对多关系)

电影还具有被视为一对一关系的日期和预算(我将它们放在 dbo.Films 中)。

Actor 可以有 1 个 fname、1 个 lname 和 0 个或多个电子邮件地址。 董事有 1 个 fname 和 1 个 lname。 你可以在下图中看到我的设计(PK是主键)。

See my db_design

1) 到目前为止,我的设计和思维方式如何?
2) 我应该如何设计 dbo.Emails 表?如果我没记错的话,这与演员是一对多的关系。
3) 假设我想获取一部电影的所有信息(标题、日期、预算、演员、导演、流派),所有信息都在一行/一行中。我想我必须使用 INNER JOIN。我尝试了以下方法,但我得到了多行相同的演员但不同的类型(实际上我认为我得到了所有可能的组合)。我使用 Temp 只是为了从结果中删除 (film) id 列。是不是太复杂了,还是我遗漏了什么?

IF OBJECT_ID('dbo.Temp', 'U') IS NOT NULL
DROP TABLE dbo.Temp

SELECT f.*, a.fname, a.lname, g.name INTO Temp
FROM [Video].[dbo].[films] f 
INNER JOIN [Video].[dbo].[film_actor] af
    ON f.id = af.film_id
INNER JOIN [Video].[dbo].[actors] a
    ON af.actor_id = a.id
INNER JOIN [Video].[dbo].[film_genre] gf
    ON f.id = gf.film_id
INNER JOIN [Video].[dbo].[genres] g
    ON g.id = gf.genre_id   

WHERE f.title = 'SomeMovie'

ALTER TABLE Temp
DROP COLUMN id
/* Get results and drop temp table */
SELECT * FROM Temp
DROP TABLE Temp

【问题讨论】:

  • 你正在以关系的方式思考。不用担心。您的数据库看起来不错。您可以添加 ActorEmails(ID、ActorID、Email)。还要在 Film_Genres、Film_Actors 和 Film_Directors 中添加 PK。
  • 1) 我应该为 Film_Genre 中的 film_id 和genre_id 添加 PK 吗? Film_Actors 和 Film_Directors 呢?这里PK的目的是什么? 2)您能否更具体地了解 .Persons 表?如果我添加 .Persons 并有 id、fname、lname、电子邮件,我将如何分辨谁是演员和谁是导演?

标签: sql sql-server database


【解决方案1】:
  1. 除了一个例外,该设计对我来说似乎很好。然而,我宁愿有一张桌子dbo.Person 或类似的东西,因为演员和导演都有一些非常人性化的属性(例如名字)。那些同时担任导演的演员又如何呢?你不会想要两个数据库条目。
  2. 关于“dbo.Emails”表,我没有发现任何问题。我希望与上述人员表有一对多的关系。因此,表格可能会有一个“Id”列、一个“PersonId”和电子邮件本身。
  3. 仅使用JOIN 语句,您将无法检索一行中的所有信息,因为JOIN 将为您提供两个结果集的每个匹配组合的一行。因此,由十名演员主演的电影将产生十行。如果那部电影属于两种类型,那么您最终将有 20 行,依此类推。有多种方法可以在一列中获取所有演员的姓名(例如,以逗号分隔),但通常这不是人们想要的。不过,这取决于您的应用程序或用例。

【讨论】:

  • 1.可以添加第三个表 Persons 并更改 Actors 和 Director,以便它们包含指向 Person 的链接。或者只用 PersonTypes 表制作 Person 表。但我更喜欢先。
  • @papatoob 你能解释一下 dbo.Person。你会有 Person.id、Person.fname、Person.lname、Person.email 吗? Film.Actor 和 Film_Director 表呢?保留还是删除?
  • @tsafou dbo.Person 会有 Id 和 name 列;如果只有一封电子邮件,那么它也会发送到那里。对于多封电子邮件,您需要一个不同的表格(见上文)。 dbo.FilmActorsdbo.FilmDirector 表仍然需要,但它们会有一个 PersonId 列,因为不会有特定的 Actor-ID 和 Director-ID。
  • 最后一个可能很愚蠢的问题。在 UI 上,我计划有一个表单,用户可以在其中输入电影、演员等的详细信息。dbo.Films 的 ID 必须发送到使用它的每个表(即 dbo.Films、dbo .FilmPersons、dbo.FilmGenres 等)?还是所有表都可能通过连接从一个表中“获取”此密钥? (同样适用于所有其他列?)
  • ID 实际上表之间的连接,所以是的,您几乎必须在任何地方使用它。
【解决方案2】:

这确实是个大话题。关于数据库规范化的整本书。

  1. Genres(ID(PK), Name) 可以。
  2. Films(ID(PK), Title, Date, Budget)可以
  3. FilmGenres(FilmID, GenreID)在这里你可以做以下事情

    一个。添加复合PKFilmGenres(FilmID(PK), GenreID(PK))

    b.添加代理 PK FilmGenres(ID(PK), FilmID, GenreID) 以及 FilmID、GenreID FilmGenres(ID(PK), FilmID(U), GenreID(U)) 上的唯一索引。 在这里,您需要 FilmID 和 GenreID 组合的唯一性。我想你明白为什么了。

  4. ActorsDirectors。在这里你可以添加 Persons(ID(PK), FirstName, LastName) 并将此表链接到 Actors(PersonID(PK,FK), ...)Directors(PersonID(PK,FK), ...)

  5. FilmActors(FilmID, ActorID) - 在这里应用第 3 条。

  6. FilmDirectors(FilmID, DirectorID) - 在这里应用第 3 条。

  7. 添加 PersonEmails(PersonID, EmailID) - 在这里应用第 3 条。

如果满足以下条件,第 4、5、6 项可以更改:

  1. PersonTypes(ID(PK), Name):导演、演员、制片人……

    Persons(ID(PK), FirstName, LastName)

    PersonTypesPersons(PersonID, PersonTypeID) - 在这里应用第 3 条。

  2. FilmActors - 不再需要了。

  3. FilmDirectors - 不再需要了。

  4. 添加 PersonEmails(PersonID, EmailID) - 在这里应用第 3 条。

【讨论】:

  • 根据您的设计,Directors 应该只有 PersonID(PK, FK) 还是更多信息,例如 FirstName、LastName?
  • 没有 FirstName,LastName 将转到 Persons 表。导演有自己的导演相关信息,演员有自己的演员相关信息
  • 好的,我明白了。我想我的设计可能不需要那个。还是我只需要演员而不需要导演? (演员只有名字、姓氏和电子邮件,导演只有名字、姓氏)。抱歉,这是我的第一次,我很困惑。
  • @Tsafou,然后坚持第二个设计,没有导演和演员表
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-24
相关资源
最近更新 更多