2011-05-12 84 views
1

我的人和一个人可以多接触其他人,所以基本上“默认”表将是:自我M:N关系

persons (id) 
contacts (person1_id, person2_id) 

有了这个模式,我不得不发出像

查询
SELECT * 
FROM  contacts c 
WHERE (person1_id = *id of person1* AND person2_id = *id of person2*) 
     OR 
     (person1_id = *id of person2* AND person2_id = *id of person1*) 

当我只插入一次这样的关系时,得到两个人之间的关系。

处理这种情况的常见做法是什么?

  1. 插入一次数据,做这样的OR查询
  2. 插入的关系的两倍,这样person1_id = ID的PERSON1和person2_id = ID的PERSON2足够
  3. 完全不同的方法?

假设:

  • 的M:N表实际上包含额外的数据,所以如果我创建两种方式的关系,我不得不重复数据
  • 这是一个核心组成部分应用和最不平凡的查询涉及至少一个子查询,确定这种关系是否存在
+2

在SQL中对无向图进行一些阅读,这就是'contacts'表代表的内容。 – 2011-05-12 23:27:44

+0

感谢您的期限:) – Maxem 2011-05-12 23:29:07

+1

确保这符合您的要求,这意味着当person1联系person2时,这与person2联系person1的意思相同。这可能不是你真正想要的;我有时会将这种差异描述为Twitter的“追随”模式与Facebook的“朋友”模式。 – xzilla 2011-05-13 03:41:01

回答

2

如果你编写插入逻辑性,比如person1_id < person2_id是适用于所有的行,然后哟你可以只写

SELECT * 
FROM contacts c 
WHERE person1_id = min(*id_of_person_1*, *id_of_person_2*) 
AND person2_id = max(*id_of_person_1*, *id_of_person_2*) 
+1

请注意,如果您必须执行诸如“所有person1联系人”之类的查询,则即使您强制执行上述建议之类的操作,也必须恢复对双方的“OR”查询(因为您不知道person1是给定关系的最小值或最大值) – xzilla 2011-05-13 03:44:50

+0

xzilla上面的注释+1:如果问题不是“这两个人有关系”,而是“谁与此人有关”,那么min-max属性不会就足够了。对于“谁是相关的”查询,我可能会将它写为'... WHERE * id_of_person_1 * IN(person1_id,person2_id)',只是为了使它更简洁并避免AND/OR优先问题。 – Alanyst 2011-05-13 12:27:04

0

为什么你不使用Join之间的表?

是这样的:

SELECT * 
FROM contact c INNER JOIN person p ON p.id = c.person1_id 

的在where和分组依据,你需要完成你的查询=)

看看这里的结果将如何显示: http://www.w3schools.com/Sql/sql_join_inner.asp

Regards,
Elkas

+0

有完全相同的问题。我仍然必须做p.id = c.person1_id或p.id = c.person2_id等 – Maxem 2011-05-12 22:55:01

+0

右连接或左连接怎么样?哼,也许我不是很了解你想要的伴侣..你能更好地解释它吗? – Elkas 2011-05-12 22:59:53

+0

鉴于: Person 1 - id:1,name:foo Person 2 - id:2,name:bar。 当FOO联系人栏中,它导致的联系人条目: person1_id:1,person2_id:2 当酒吧想联系富,我在它是否已经存在接触表一看,就做到这一点,我必须发出这个查询: 从联系人选择哪里person1_id = 1 AND persond2_id = 2或person1_id = 2 AND person2_id = 1。 我只是想知道这种情况下的常见做法,有这样的一个OR并不真正“感觉”正确。 – Maxem 2011-05-12 23:03:36

0

试试这个伙伴=)

SELECT c.person1_id as id_person_1, c.person2_id as id_person_2, p1.name as name_person_1, p2.name as name_person_2 
FROM contact c 
LEFT JOIN person p1 ON p1.id = c.person1_id 
RIGHT JOIN person p2 ON p2.id = c.person2_id; 

我不知道这是否会工作..但给它尝试队友=)

+0

顺便说一句,如果我没有弄错我前几次有同样的问题..得到M-N关系数据。你和我之间的区别是,我有这样的成员关系 - membre_has_group - 组,你有人 - 联系人 - 人。检查他们给我的答案。它帮助了很多。 http://stackoverflow.com/questions/5487352/mysql-query-relations-m-m-table – Elkas 2011-05-12 23:29:05

0

“插入关系的两倍,这样person1_id = PERSON1的ID和person2_id = PERSON2的ID就足够了”

这就是我个人的做法。它允许处理A具有B的联系细节而不是其他方式的情况(例如,当女孩离开时,女孩在酒吧给予她一个号码“给我打电话”)。它也使查询更简单。