MySQL结构::友谊

时间:2010-10-23 15:04:07

标签: mysql database-design structure

很多人说我应该创建一个友情表( userid friendid )。

我的问题是:

每个友情都不会有双重记录 喜欢
12 5 的朋友 +
5 12

的朋友

有没有办法阻止

| OR |

我应该忽略

3 个答案:

答案 0 :(得分:6)

您可以使用至少两种方法:

  1. 确保userid始终小于friendid
  2. 在两个方向存储每个关系(即存储a,b和b,a)。
  3. 第二种方法的存储成本是存储的两倍,并且是多余的,但它确实意味着某些查询可以更简单并且性能更好。例如,考虑使用每种方法获取用户'a'和'b'的所有常见朋友:

    方法1:

    SELECT friendid
    FROM
    (
        SELECT friendid FROM friendships WHERE userid = 'a'
        UNION
        SELECT userid FROM friendships WHERE friendid = 'a'
    ) T1
    JOIN
    (
        SELECT friendid FROM friendships WHERE userid = 'b'
        UNION
        SELECT userid FROM friendships WHERE friendid = 'b'
    ) T2
    ON T1.friendid = T2.friendid
    

    方法2:

    SELECT T1.friendid
    FROM friendships T1 
    JOIN friendships T2
    ON T2.userid = 'b' AND T1.friendid = T2.friendid
    WHERE T1.userid = 'a'
    

答案 1 :(得分:1)

我会问: 有人可以成为自己的朋友吗? “友谊”是什么意思 - 它是双向的还是单向的。 如果是双向的,那么一条记录就行了,对吧?如果是单向的,则需要两个记录。 如果有人不能成为自己的朋友,那么你在数据输入页面中实现一个业务规则(在网页中,这对于javascript是有益的),其中friend1 id<> friend2 id  不确定我同意'不到' - 他们不能平等

答案 2 :(得分:1)

缺少上下文,问题太孤立,答案非常有限。线程不完整。

首先,为了理解,所呈现的Friend表本身并不存在。它是User表的子级,具有UserId PK。 UserId和FriendId都是UserId的FK。

由于友谊是双向的或双向的(我们在这里排除未交往的恋人和潜行者!),然后单行识别两个方向的关系。

任何列的命名都有很强的含义,所以我会避免(UserId,FriendId)暗示层次结构或单向关系,这是错误的。我建议(朋友1,朋友2),当然你需要PK((朋友1,朋友2)。

尚未确定的是,我们仍然没有阻止重复([5,12]和[12,5]),这是你想要防止的非常多的冗余。我们需要一个规则,强制执行一个命令,Friend1总是小于Friend2。

还有其他关系,例如物料清单或家谱,其中包含Assemblies和COmponents,它们需要更多内容。例如(AssemblyId,ComponentId)或(ParentID,ChildId),该规则不适用:part可以是Assembly中的Component,也可以是Assembly本身。这需要两行。仍然没有重复。