自我:n关系

时间:2011-05-12 22:17:05

标签: postgresql database-schema

我有人和一个人可以联系多个其他人,所以基本上“默认”表格是:

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 = person1的 id 和person2_id = id为person2
  3. 一种完全不同的方法?
  4. 假设:

    • m:n表实际上包含其他数据,因此如果我为两种方式创建关系,我必须复制数据
    • 这是应用程序的核心部分,大多数非平凡的查询至少涉及一个确定是否存在这种关系的子查询

4 个答案:

答案 0 :(得分: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 :(得分:0)

为什么不在表之间使用Join?

类似的东西:

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

您需要填写的地点和分组是查询=)

看一下结果将如何显示: http://www.w3schools.com/Sql/sql_join_inner.asp

的问候,
Elkas

答案 2 :(得分: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;

我不知道它是否会起作用..但是试试吧mate =)

答案 3 :(得分:0)

“插入关系两次,以便person1_id = person1的id和person2_id = person2的id就够了”

这就是我亲自做的。它允许处理A具有B的联系细节而不是相反的情况(例如,一个女孩在酒吧给她一个她的号码,当她走出去时“打电话给我”)。它还使查询更简单。