Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何在具有三元关系的表上进行选择?_Sql_Database Design - Fatal编程技术网

Sql 如何在具有三元关系的表上进行选择?

Sql 如何在具有三元关系的表上进行选择?,sql,database-design,Sql,Database Design,我正在做一个学习项目,为图书馆设计一个数据库。图书馆出借书籍、视频和音频。为了好玩,我决定把为一项工作做出贡献的人塑造成三元关系。这使得昆汀·塔兰蒂诺(Quentin Tarrantino)更容易成为同一部电影中的导演、作家和演员,也更容易成为一些书籍的作者,所有这些作品都没有冗余的人物以及他们在创作作品中扮演的角色 我把三个基本实体称为参与者、角色和作品 我遇到了一个问题,因为我不确定我应该做什么,即使是在一个简单的案例中列出一本书。我是否会为每个参与者/角色对创建一个单独的行?或者,有没有一

我正在做一个学习项目,为图书馆设计一个数据库。图书馆出借书籍、视频和音频。为了好玩,我决定把为一项工作做出贡献的人塑造成三元关系。这使得昆汀·塔兰蒂诺(Quentin Tarrantino)更容易成为同一部电影中的导演、作家和演员,也更容易成为一些书籍的作者,所有这些作品都没有冗余的人物以及他们在创作作品中扮演的角色

我把三个基本实体称为参与者、角色和作品

我遇到了一个问题,因为我不确定我应该做什么,即使是在一个简单的案例中列出一本书。我是否会为每个参与者/角色对创建一个单独的行?或者,有没有一种方法可以让生成的talbe具有某种“特别”专栏(例如,一本书的作者、插图画家、翻译人员)

感觉使用这个三元关系已经将层次结构注入了我的数据库,我想知道如何最好地处理它(请不要消除三元关系)

[结语]
我的问题处理得很好。Stefan,我确实有一个中间表,让你(和其他读者)知道。看起来三元关系为应用程序程序员提供了数小时的乐趣。

正如@Stefan H所指出的,您确实还需要一个连接表。您通过使用contributors表来减少冗余,但看起来您将把角色硬编码到它们之间的联接表中。您还希望抽象出角色,因此您的表应该如下所示:

Contributor
    ContributorID PK
Role
    RoleID PK
Work
    WorkID PK
ContributorRoleInWork
    ContributorRoleInWorkID PK
    (
        ContributorID FK
        RoleID FK
        WorkID FK
    ) --These three form a unique alternate key as well

为了回答你的实际问题,是的,你会为每一个贡献者或参与工作得到一排回复,但这正是你想要的。当您列出一本书的信息时,您希望为每个参与者/角色组合返回一行。为了便于显示信息,您可以根据您想要显示数据的方式,按参与者或角色进行排序/分组。

要回答这个问题,是的,每个参与者/角色都会有一行,例如 约翰·多伊是电影《福》的执行制片人和导演

            WORK             CONTRIBUTOR           ROLE
            Foo              John Doe             Director
            Foo              John Doe             Executive Producer
因此,您将有四个表(每个实体一个表和链接表):

链接表的主键是三元组:

          WORKS_CONTRIBUTORS
          workid
          contributorid
          roleid

您不能真正拥有特别的列,因为每个列中可以有不同数量的行。例如,一本书可能有一位作者,三位插图画家,而没有翻译人员

要获得一本书的贡献者列表,您必须选择与之相关的所有角色-贡献者对,可能首先按角色排序,以便更容易地分组,然后按角色对贡献者进行分组并显示在页面上

要编辑书籍的数据,您必须验证所需角色的贡献者是否存在(例如,至少一位作者)。这可以部分地通过一个不允许删除最后一个作者的ON-UPDATE和ON-DELETE触发器来完成;对于插入,您需要其他东西


我还将使用一个“模板”表,列出每种工作类型的可能角色
(需要工作类型、角色类型)
。如果
是必需的
为true,则该角色必须存在于有效的工作中,如果为false,则该角色是允许的,但是可选的。只允许在表中为给定的
工作类型明确列出角色(因此您没有书籍的作曲家或音乐曲目的插图画家)。

我认为这可能是最简单的解决方案(但不是最佳方案):

这样,如果您想知道给定书籍中的所有贡献者及其角色,可以使用隐式连接和

SELECT * FROM people,roles WHERE roles.BookID = [your book id] AND people.ID = roles.PersonID
同样,要获得某个人的所有贡献,你可以

SELECT * FROM books, roles WHERE roles.PersonID = [your person id] AND books.ID = roles.BookID
相反,如果你只想看别人导演的电影:

SELECT * FROM books, roles WHERE roles.PersonID = [your person id] AND roles.Role = "director" AND books.ID = roles.BookID

有更好的方法来编写这些查询:获取SQL方言的参考手册并查找联接。

有什么原因使您没有简单地创建一个Contributors表,然后使用该表中的外键到书本、视频或音频表中?看起来你把这件事弄得太复杂了。而且,如果你一意孤行,那么你需要一个参与者和角色之间的交集表,以及你的角色和作品之间的交集表。因为这两种关系都是多对多的,我觉得他做得不错。它可能有助于在代码中显示表结构(即create table语句或基本表定义)。Stefan,我同意可以更直接、更简单地对其进行建模,但以下是我的理由:首先,我想了解三元关系在代码中是如何工作的。第二,我没有书/视频/等的单独表——而是使用专门化层次结构来子类化。第三,它似乎可以消除冗余——现在我不太确定。谢谢,你回答了我的主要问题,并给了我一些具体的想法,如果我着手开发前端应用程序,该如何进行。
SELECT * FROM books, roles WHERE roles.PersonID = [your person id] AND books.ID = roles.BookID
SELECT * FROM books, roles WHERE roles.PersonID = [your person id] AND roles.Role = "director" AND books.ID = roles.BookID