试图弄清楚如何查询通过自引用多对多表连接的不同实体组。整个下午一直在戳它,以为我会问这里是否有其他人有想法。
例如,一个人有一群朋友,这些群组是独占的(即群组之间没有重叠 - 如果你愿意的话,还有一堆派系)。表结构可能如下所示:
person
| id | name |
| 1 | bob |
| 2 | frank |
| 3 | chuck |
| 4 | nancy |
| 5 | alice |
| 6 | sally |
cliques
| from_person_id | to_person_id |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 4 | 5 |
| 4 | 6 |
| 5 | 4 |
| 5 | 6 |
| 6 | 4 |
| 6 | 5 |
(Bob是Frank和Chuck的朋友,Frank是Bob和Chuck的朋友,Chuck是Bob和Frank的朋友等。)
我可以获得一堆与每个人的朋友相关的集合,但无法弄清楚如何将其煮沸。最终,我真正喜欢的是一个返回不同集团成员的查询,例如
| cliques |
| 1, 2, 3 |
| 4, 5, 6 |
但是,当然,除非我使用像group_concat(MySQL)或array_agg(PostgreSQL)这样的东西,否则SQL不会那样工作。我并不是严格反对这种方法,但我宁愿避免引入特定于后端的实现(我实际上使用的是Django的ORM,但不想分散这些细节)。
我的问题是:
答案 0 :(得分:0)
如果您正在寻找连接的子图,这是一种方法。
您可以通过其中任何节点的最小ID来表征连接的子图。
从表开始存储子图ID,如:
create table subgraphids (
personid int,
subgraphid int
);
初始化:
insert into subgraphids(personid, subgraphid)
select personid, min(subgraphid)
from (select from_person_id as personid,
least(from_person_id, to_person_id) as subgraphid
from cliques
union all
select to_person_id, least(from_person_id, to_person_id)
from cliques
) t
group by personid;
现在你有了暂定的子图。要更新它们,请使用类似的类型查询:
update subgraphid
set subgraphid = (select min(s.subgraphid)
from cliques c join
subgraphid s
on c.from_person_id = s.personid or
c.to_person_id = s.personid
where subgraphid.personid = clique.from_person_id or
subgraphid.personid = click.to_person_id
);
重复此操作直到没有更新行。您可以明确检查该条件:
select count(*)
from subgraphid
where subgraphid > (select min(s.subgraphid)
from cliques c join
subgraphid s
on c.from_person_id = s.personid or
c.to_person_id = s.personid
where subgraphid.personid = clique.from_person_id or
subgraphid.personid = click.to_person_id
);
这将在原始图表中找到连接的子图。迭代需要在SQL之外的调用代码中进行。