表有3个分离度

时间:2014-05-22 08:30:33

标签: php mysql

我正在寻找一个查询来在MySQL中创建一个表,其中包含两个用户之间的分离程度。我已经找到了Degrees of Separation Query。但是,如果我理解正确,那将导致与共同朋友推荐的朋友列表。我正在寻找的是略有不同。

我在用户之间有一个“朋友”的表(不包含重复的关系,如1到2和2到1)。

  

friendsidinitiator_user_idfriend_user_idis_confirmed

我想要创建的是一张表格,其中包含朋友,朋友的朋友和FoFoF之间的所有关系。像这样:

  

relation_degreesidfirst_user_idsecond_user_idrelation_degree

所以relation_degree列只包含值1(朋友),2(FoF)和3(FoFoF)。

我能够在Excel中完成它,但是我的朋友存储在矩阵中,这使得计算IMO更容易一些。我希望有人能够在MySQL中给我一些提示。

谢谢!


编辑:在Fluffeh的帮助下,我找到了解决问题的方法。

  1. 我在名为degree_one的表格中存储了两个方向的关系(如1-2和2-1,因此没有确认栏)
  2. 然后我使用了来自fluffeh的第一和第二学位的查询来制作第一个和第一个的表格。二级关系。我添加了一个WHERE用户<>朋友声明过滤关系(我想这是为什么来自fluffeh的查询对于三度关系的工作不正常)
  3.    `Create table degree_two
       select
       mb.user as User,
       mb.friend as Friend,
       min(mb.rel)  as relation_degree
    
         

    这           (             选择                   1作为rel,                   fr1.User,                   fr1.Friend               从                   degree_one fr1

              union all
    
          select
              2 as rel,
               fr2.User,
               fr3.Friend
           from
               degree_one fr2
                   left outer join degree_one fr3
                       on fr2.Friend=fr3.User
    
    
                    ) mb
    
       Where user <> friend
    
    
    
     group by
          mb.User,
          mb.Friend
    
    1. 然后我用这个表做几乎相同的查询。 select语句位于degree_two表上,但外连接仍然来自degree_one表。
    2.    Create table degree_three
          select
              mb.user as User,
              mb.friend as Friend,
              min(mb.relation_degree)  as relation_degree
          from
              (
                   select
                      fr1.relation_degree,
                      fr1.User,
                      fr1.Friend
                  from
                      degree_two fr1
      
      
                union all
      
            select
                  3 as rel,
                  fr2.User,
                  fr3.Friend
              from
                  degree_two fr2
                      left outer join degree_one fr3
                          on fr2.Friend=fr3.User
      
      
                      ) mb
      
      Where `user` <> `friend`
      
      group by
          mb.User,
          mb.Friend
      

      这是一种解决方法,但它给了我想要的输出。我仍然想知道为什么来自fluffeh的查询无法正常工作,因为我真的想要一个查询作为解决方案。我将继续讨论这个问题...我希望有人可以帮助我将这些查询合并为一个。

2 个答案:

答案 0 :(得分:1)

您可以使用外部联接返回表格本身...

select
    mb.initiator_user_id as first_user_id,
    mb.friend_user_id as second_user_id,
    mb.rel as relation_degree
from
    (
        select
            1 as rel,
            fr1.initiator_user_id,
            fr1.friend_user_id
        from
            friends fr1

        union all

        select
            2 as rel,
            fr2.initiator_user_id,
            fr3.friend_user_id
        from
            friends fr2
                left outer join friends fr3
                    on fr2.friend_user_id=fr3.initiator_user_id
        // and again etc or in a code loop (not really done these much)
    ) mb

基本上,似乎你的ID可以从friend1链接到friend2,但结构也允许一个查询,允许friend1使用friend2来查看他们的朋友是谁 - 你可以轻松地将这些结果与学位结合起来够了。

编辑:根据评论解决问题:

select
    mb.initiator_user_id as first_user_id,
    mb.friend_user_id as second_user_id,
    min(mb.rel)  as relation_degree
from
    (
        select
            1 as rel,
            fr1.initiator_user_id,
            fr1.friend_user_id
        from
            friends fr1
        where is_confirmed = 1

        union all

        select
            2 as rel,
            fr2.initiator_user_id,
            fr3.friend_user_id
        from
            friends fr2
                left outer join friends fr3
                    on fr2.friend_user_id=fr3.initiator_user_id
                    and fr3.is_confirmed = 1
        // and again etc or in a code loop (not really done these much)
    ) mb
group by
    mb.initiator_user_id,
    mb.friend_user_id

编辑:根据评论添加第三层关系:

select
    mb.initiator_user_id as first_user_id,
    mb.friend_user_id as second_user_id,
    min(mb.rel)  as relation_degree
from
    (
        select
            1 as rel,
            fr1.initiator_user_id,
            fr1.friend_user_id
        from
            friends fr1
        where is_confirmed = 1

        union all

        select
            2 as rel,
            fr2.initiator_user_id,
            fr3.friend_user_id
        from
            friends fr2
                left outer join friends fr3
                    on fr2.friend_user_id=fr3.initiator_user_id
                    and fr3.is_confirmed = 1
        union all
        select 
            3 as rel, 
            fr4.initiator_user_id, 
            fr5.friend_user_id 
        from 
            friends fr3 
                left outer join friends fr4 
                    on fr3.friend_user_id=fr4.initiator_user_id 
                    and fr4.is_confirmed = 1
                left outer join friends fr5
                    on fr4.friend_user_id=fr5.initiator_user_id 
                    and fr5.is_confirmed = 1
        // and again etc or in a code loop (not really done these much)
    ) mb
group by
    mb.initiator_user_id,
    mb.friend_user_id

答案 1 :(得分:0)

此查询为我提供了所需的解决方案结果:

Create table degree_two
select
    mb.user as User,
    mb.friend as Friend,
    min(mb.rel)  as relation_degree
from
    (
           select
            1 as rel,
            fr1.User,
            fr1.Friend
        from
            degree_one fr1

            union all

        select
            2 as rel,
            fr2.User,
            fr3.Friend
        from
            degree_one fr2
                left outer join degree_one fr3
                    on fr2.Friend=fr3.User
                    where fr2.user <> fr3.friend

         union all       

         select 
            3 as rel, 
            fr4.user, 
            fr6.Friend
        from 
           (degree_one fr4 
                left outer join  degree_one fr5 
                    on fr4.friend=fr5.user
                    and fr4.user <> fr5.friend

                    left outer join  degree_one fr6
                    on fr5.friend = fr6.user
                   and fr5.user <> fr6.friend)
           where fr6.friend  IS NOT NULL           


                  ) mb

group by
    mb.User,
    mb.Friend

感谢Fluffeh的帮助!