MySQL:在连接后计算重复项而不进行过滤/分组

时间:2014-04-09 21:10:07

标签: mysql sql join count

我希望这不是重复,我搜索了一段时间没有任何有用的结果。

我有一个对象表(带有主键)和一个关系表。每个关系通过外键(obj_1和obj_2)引用两个对象。 obj_1和obj_2的组合是唯一的,因此我可以代表各种网络。

现在我想选择位于至少两个其他点之间的点(例如,具有多个连接)。我通过以下查询实现了这一点:

select r1.obj_1,  r1.obj_2 as hop, r2.obj_2
from t_relations r1
inner join t_relations r2 on r1.obj_2 = r2.obj_1

现在,我的问题是我希望看到每个跃点的连接数量,但是没有过滤(我需要选择所有行,因此group by不是一个选项)。我怎么能这样做?


根据要求,提供一些示例数据。为简单起见,我假设t_relations中的数字是实际对象。

t_relations

ID |  obj_1 | obj_2
 1 |   T1   |   T2
 2 |   T3   |   T2
 3 |   T4   |   T2
 4 |   T4   |   T3

预期产出:

 obj_1 |  hop |  obj_2 | count
  T1   |  T2  |   T3   |   3    # 3 connections with 2
  T3   |  T2  |   T4   |   3
  T4   |  T2  |   T1   |   3
  T4   |  T3  |   T1   |   1    # 1 connection via 3
  T2   |  T4  |   T1   |   1    # 1 connection with 4 in the middle

正如您所希望看到的那样,我希望查询“遍历”网络,采用所有可能的路由并省略重复(如1-2-4,这将是4-2-1的冗余)。我认为我的查询确实实现了这一点......计数就是问题。

1 个答案:

答案 0 :(得分:1)

如果我理解,每行是undirected graph的两个点之间的直接连接,并且(根据您的查询)您希望获得两个点之间的连接数一个跳。我对吗?您可以使用此查询来实现此目的(可能有一个更简单的解决方案,但这个解决方案按指定的方式工作):

select distinct p1, tmp.hop, p2, count from (
    select if(p1 < p2, p1, p2) as p1, hop, if(p1 < p2, p2, p1) as p2 from (
        select r1.obj_1 as p1, r1.obj_2 as hop, r2.obj_2 as p2
        from t_relations r1 inner join t_relations r2 on r1.obj_2 = r2.obj_1
            union
        select r1.obj_2 as p1, r1.obj_1 as hop, r2.obj_2 as p2
        from t_relations r1 inner join t_relations r2 on r1.obj_1 = r2.obj_1
            union 
        select r1.obj_1 as p1, r1.obj_2 as hop, r2.obj_1 as p2
        from t_relations r1 inner join t_relations r2 on r1.obj_2 = r2.obj_2
            union
        select r1.obj_2 as p1, r1.obj_1 as hop, r2.obj_1 as p2
        from t_relations r1 inner join t_relations r2 on r1.obj_1 = r2.obj_2
    ) tmp where p1 <> p2
) tmp inner join (
    select hop, count(*) as count from (
        select distinct p1, hop, p2 from (
            select if(p1 < p2, p1, p2) as p1, hop, if(p1 < p2, p2, p1) as p2 from (
                select r1.obj_1 as p1, r1.obj_2 as hop, r2.obj_2 as p2
                from t_relations r1 inner join t_relations r2 on r1.obj_2 = r2.obj_1
                    union
                select r1.obj_2 as p1, r1.obj_1 as hop, r2.obj_2 as p2
                from t_relations r1 inner join t_relations r2 on r1.obj_1 = r2.obj_1
                    union 
                select r1.obj_1 as p1, r1.obj_2 as hop, r2.obj_1 as p2
                from t_relations r1 inner join t_relations r2 on r1.obj_2 = r2.obj_2
                    union
                select r1.obj_2 as p1, r1.obj_1 as hop, r2.obj_1 as p2
                from t_relations r1 inner join t_relations r2 on r1.obj_1 = r2.obj_2
            ) tmp where p1 <> p2
        ) tmp
    ) tmp group by hop
) tmp2 on tmp.hop = tmp2.hop;