同桌上的多对多

时间:2013-06-15 22:22:49

标签: mysql

有趣的是,我从未遇到过这个!

我从来没有想到一个人可以在一张桌子上拥有“多对多”的关系 - 直到我开始研究一个用户可以互相“互相交流”的系统(社交网络)。

标准查找表,至少在我习惯使用它的方式,在这里不合适。让我们保持简单:

用户表有“id”和“name”列。

User_relationship表有“uid1”和“uid2”,表示“朋友”或“萌芽”或“好友”或“其他任何”的用户。

很明显这里的问题是什么 - uid1和uid2是来自同一个表的同一列的相同数据类型,这意味着唯一键变得有缺陷。

例如为: uid1 = 1 uid2 = 2

与:

相同

uid1 = 2 uid2 = 1

因此,如果执行错误,则可以返回2条记录或0条记录。

本着设计好桌子的精神,我不想两次扫描整个表来检查现有值。

处理这个有什么技巧吗?这是一个从未发生过的设计问题,它让我感到烦恼,因为我知道有一些简单的技巧可以让它发挥作用。

在你问之前,我还没有尝试过任何东西,因为我已经看到我最喜欢的关联方式(查找表)不足以满足我的需求,我需要一些帮助 - 我找不到任何东西SO或Google :(

提前致谢。

4 个答案:

答案 0 :(得分:7)

  

意味着唯一键变得有缺陷。

uid1 = 1 uid2 = 2
     

与:

相同
uid1 = 2 uid2 = 1

不,不是。

例如,在Facebook上,我有很多客户发出请求成为我从未接受过的“朋友”...因为他们只是熟人。

同样,我可能会将一些人标记为最好的朋友,但他们没有回应,反之亦然。或许我忽略了一些而他们不是。

基本上,(uid1, uid2)元组中的信息比仅仅ID更多。

确保在决定添加例如此类情况之前,您永远不需要处理这些情况。你桌子上的uid1 < uid2约束。

答案 1 :(得分:7)

如果您描述的关系是对称的,如“Bob是Joe的朋友”意味着“Joe也是Bob的朋友”,那么您可以在代码中确保2个用户ID中较小的一个进入第一列,较大的一列进入第二列。这种约束几乎可以确保查找表中的记录是唯一的。这也意味着当您执行查找时,通常必须搜索两列。

例如,如果您尝试获取Bob的所有朋友,则必须在任一列中查询具有Bob ID的记录。这会导致更多代码,并可能对性能产生影响。

如果关系可以是不对称的,如“Bob是Joe的朋友”并不一定意味着“Joe也是Bob的朋友”,那么每对用户需要2个条目:Bob - Joe和Joe - 鲍勃这意味着您的查找表将包含两倍的条目,并且您的站点对跟踪器非常友好:D当然,即使您的关系是对称的,您仍然可以选择应用此系统。

使用此方法,如果您想获得Bob的所有朋友,您只需在第一列中选​​择带有Bob ID的记录。这可能意味着更快的查找速度和更少的代码供您编写,但同样,这意味着您在数据库中占用更多空间。

答案 2 :(得分:2)

这并不罕见。

通常所做的是有一个表,就像在大多数关系中一样,它由两个列组成,每个列都是构成主键的两个表的id。

正如您所说的userId1和userId2。如有必要,可以将属性添加到关系中(例如友谊分类)。

当用户1与用户2成为朋友时,通常有两个插入,(1,2)和(2,1)。

与defriending相同的事情,需要有两个删除。

您最终可能会将自己视为朋友,这可能对系统的实际运作至关重要。如果用户只能查看他朋友的照片,那么如果他不是自己的朋友,某些系统可能不允许他看到他自己的照片。

它非常依赖于如何在数据库上编写应用程序。

答案 3 :(得分:1)

我同意其他人的说法,为关系(1:2和2:1)设置2个插入并不是一个坏主意。这实际上有助于扩展现代社交网络中常见的一些功能。我能想到的一些实际使用案例是关系或其他属性的描述。虽然个人仍然是朋友,但他们保持着彼此不同的环境。在1:2关系中,Bob正在关注Joe的更新并将他列在最好的朋友列表中(添加bff列),而在2:1中Joe没有Bob在bff列表中并且不关心他的帖子(在列之后)