很多人说我应该创建一个友情表( userid , friendid )。
我的问题是:
每个友情都不会有双重记录? 喜欢:
12 是 5 的朋友
+
5 是 12
有没有办法阻止?
| OR |
我应该忽略?
答案 0 :(得分:6)
您可以使用至少两种方法:
userid
始终小于friendid
。第二种方法的存储成本是存储的两倍,并且是多余的,但它确实意味着某些查询可以更简单并且性能更好。例如,考虑使用每种方法获取用户'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本身。这需要两行。仍然没有重复。