试图弄清楚如何查询通过自引用多对多表连接的不同实体组。整个下午都在戳它,以为我会问这里是否有其他想法。

例如,某人有一组朋友,而这些组是互斥的(即组之间没有重叠-如果您愿意,则是一堆小集团)。表结构可能看起来像这样:

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/

10-09 20:15