如何表示对称的多对多关系

时间:2010-08-23 17:31:59

标签: database-design

假设我有一个名为USER的实体,并且两个USER之间存在关系FRIENDSHIP 因此,我有一个表'USER'和一个关系表'FRIENDSHIP'

   

USER id firstName LastName 1 taher chhabrawala 2 john Dsouza 3 rahul singh 4 deepak patel

Friendship id id 1 2 1 3 1 4 4 1 4 3

在上表中,我存储了两次相同的信息,即“taher是deepak的朋友,而deepak是taher的朋友”

有没有办法减少这种冗余?

5 个答案:

答案 0 :(得分:8)

嗯,你当然可以假设所有友谊都是对称的并且只存储一次友谊,但这意味着当你想要查询所有Taher的朋友时,你必须在任一列中寻找他的ID。 / p>

或者,您可以拥有一个单独的关系ID表,然后是一个与用户关系的一对多表。这样做的好处是,如果有一天你想要它,它将允许多人关系,并允许你添加关于关系的元数据(当它开始时,谁建议它,无论如何)。

   User                
Id    Name          
1     Taher         
2     Deepak        

Relationship              
Id     StartDate           
1      2010-08-23

UserRelationship
RelationshipId UserId
1                1
1                2

另一方面,在Facebook上,例如,我可以“交朋友”,他们可以决定不与我交朋友。如果你没有现在正在使用的“冗余”方法,你将如何表现这种尚未互惠的友谊?

答案 1 :(得分:3)

制定一个规则,例如“第一个ID值始终低于第二个ID值”,这样就可以确保没有重复项。

在这种情况下,对(4,1)无效,对(4,3)将存储为(3,4)。

答案 2 :(得分:1)

显而易见的解决方案是每对朋友只存储1条记录。但是,保持独特性变得更加困难;与“冗余”解决方案相比,获取/更新/删除朋友关系的所有查询都变得更加复杂。此外,具有2条记录的解决方案允许您维护朋友请求(例如,UserA要求UserB成为朋友.UserB可以确认或拒绝此请求)。所以我认为在这种情况下冗余是完全有效的。

答案 3 :(得分:0)

如果您决定使用对称设计,那么确保每个友谊始终是双向的可能是有用的。你可以试试这个:

CREATE TABLE Friendship
 (UserId1 INT NOT NULL REFERENCES Users (UserId),
  UserId2 INT NOT NULL,
  PRIMARY KEY (UserId1, UserId2),
  FOREIGN KEY (UserId2, UserId1) REFERENCES Friendship (UserId1, UserId2));

INSERT INTO Friendship (UserId1, UserId2)
VALUES (1,2),(2,1);

答案 4 :(得分:0)

如果存储这两行,则需要强制执行完整性规则,以确保友谊始终成对出现。

只在表格中存储一行(例如,FR),并创建一个SYMFR视图

SELECT x,y FROM FR 联盟 选择x为y,y为x FROM FR