试图弄清楚如何查询通过自引用多对多表连接的不同实体组。整个下午都在戳它,以为我会问这里是否有其他想法。
例如,某人有一组朋友,而这些组是互斥的(即组之间没有重叠-如果您愿意,则是一堆小集团)。表结构可能看起来像这样:
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 |
(鲍勃是弗兰克和查克的朋友,弗兰克是鲍勃和查克的朋友,查克是鲍勃和弗兰克的朋友,等等。)
我可以得到一堆与每个人的朋友有关的布景,但是却不知道该如何精简。最终,我真正想要的是一个返回不同派系成员集的查询,例如
| cliques |
| 1, 2, 3 |
| 4, 5, 6 |
但是,当然,除非我使用group_concat(MySQL)或array_agg(PostgreSQL)之类的SQL,否则SQL不会那样工作。我并不严格反对这种方法,但我希望避免引入特定于后端的实现(我实际上是在使用Django的ORM,但不想分散这些细节)。
我的问题是:
我是否试图通过这种方式对事物建模来树错了树?
有没有办法在不调用调用代码迭代的情况下组合不同的团体?我不要求每个集群有一行,因为这需要特定于数据库的聚合,但是可能生成了一个id-per-clique和一组(clique_id,member_id)元组,然后可以在调用代码中进行汇编?
最佳答案
如果您正在寻找连接的子图,这是一种方法。
您可以通过其中任何节点的最小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之外的调用代码中进行。
关于sql - 如何查询通过自引用多对多表连接的不同实体组?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15725188/