2012-01-18 65 views
2

我想创建一个表格,我的用户可以在这里关联一个友谊。与此同时,这张表格将与我想成为我尝试处理的各种其他表格之间的一对多关系一起工作。在mysql数据库中存储友谊关联的正确方法是什么

现在我想到的是这样的

member_id,friend_id,活动,日期

member_id将使得呼叫的用户的列,friend_id会被他们的朋友列试图绑定到,活动将是一种切换0 =挂起,1 =活动,日期将只是该特定行上最后一个活动的记录日期。

现在我的困惑是,如果我要查询,我通常会查询member_id,然后根据关联的friend_id将查询的其余部分根据相应的数据显示给合适的人员。因此,考虑到这种逻辑,这使得我认为每个请求必须有2行。其中一个请求的member_id和请求的friend_id插入到表中,然后是相反的,所以我可以每次都相应地进行查询。所以在本质上,它就像对待这个特定表所要求的每一个动作一样,我需要做出2个动作来使其工作。 就优化而言,哪一点对我来说都没有意义。因此,在我所有的问题中,处理这种关系的数据的正确方法是什么?或者,我是否真的认为这是一种处理它的方法?

+0

您的第一个模型完美无缺。对于第二部分,找到两个方向,这里已经有很多答案。短版本:建立您的SELECT查询有点花哨,您可以轻松获得两个方向。 – 2012-01-18 01:07:22

回答

6

如果友谊是总是相互的,那么你可以将数据冗余之间进行选择更简单的查询的缘故(即具有行两个方向),或学习生活稍微更复杂的查询。除非有一个令人信服的理由,否则我个人会避免数据冗余 - 不仅仅是浪费空间和性能,但是在执行时需要小心 - 一个简单的CHECK不能引用其他行,并且取决于您的DBMS的一个触发器可能会受限于它可以对变异表进行的操作。

一个简单的方法确保每友谊只有一行是始终插入member_id较低值和较高的friend_id值(做出约束CHECK (member_id < friend_id)到付诸实施)。然后,当你查询,你必须在两个方向搜索 - 例如,寻找特定的人(由person_id标识)的所有的朋友会是这个样子:

SELECT * 
FROM 
    person 
WHERE 
    id <> :person_id 
    AND (
     id IN (
      SELECT friend_id 
      FROM friendship 
      WHERE member_id = :person_id 
     ) 
     OR 
     id IN (
      SELECT member_id 
      FROM friendship 
      WHERE friend_id = :person_id 
     ) 
    ) 

顺便说一句,在这个方案中,您'd可能想要将member_idfriend_id重命名为friend1_idfriend2_id ...

+0

请注意:在上面的代码中使用IN关键字并不是一个好主意,因为它在MySQL中没有优化。在大型表格中,它可能会导致缓慢的结果。 – maliayas 2012-06-11 01:26:27

+0

@maliayas是的,MySQL往往不够优化子查询。在这种特殊情况下,这是否是一个实际问题,只能通过对实际数据量进行测量来确定。我的直觉是这里不应该有性能问题,但是如果我错了,那么还有其他方式来表达本质上相同的查询,这可以避免MySQL在这方面的不足(例如JOIN)。 – 2012-06-11 01:37:13

1

美丽 - 你的桌子没有问题。

ALSO: 我不知道这是否基数是“一对多”或“多对多”:

http://en.wikipedia.org/wiki/Cardinality_%28data_modeling%29

问:我是来查询我通常查询为member_id则立足 其余查询相关关friend_id的的数据显示相应 给正确的人

答:坦率地说,我没有看到可以查询“会员与朋友”或“朋友与会员”(或任何其他组合 - 例如分享朋友的朋友)。再一次,它看起来不错。

0

介绍一个辅助表所示:

users 
user_id, name, ... 

friendship 
user_id, friend_id, .... 

select u.name as user, u2.name as friend from users u 
    inner join friendship f on f.user_id = u.user_id 
    inner join users u2 on u2.user_id = f.friend_id 

我觉得这是非常相似的,你有什么,只是把查询作为一个例子。

+0

如果添加了关系的两边,可能存在重复条目。 – Kenaniah 2012-01-18 01:09:38

+0

如果您看到列的名称,则不是真的。这是一种单向关系,如果双方都加在一起,两行就有意义。 – 2012-01-18 01:11:21

+0

这两行输出使连接结构复杂化,因此需要添加“GROUP BY”才能返回一个不同的集合,否则会导致连接到它的数据中出现重复。 – Kenaniah 2012-01-18 01:15:33

5

两种方式来看待它:

WHERE ((friend_id = x AND member_id = y) OR (friend_id = y AND member_id = x)) 

将允许您通过简单的陈述关系的一侧进行查询。如果添加了双方,则此方法仍然可以工作,而不会导致重复的行被返回。

相反,添加关系的双方,让你查询包括

WHERE friend_id = x AND member_id = y 

不仅使查询更容易编写,也更容易规划(意味着更好的性能DB)。

我的投票是为后面的选项。

相关问题