用pl / sql计算6度分离的算法和查询?

时间:2015-04-17 04:24:14

标签: java sql oracle graph plsql

我有一个名为friendgraph的表(friend_id,friend_follower_id),我想为给定的朋友和给定的度数计算6度的分离度。 该表如下所示:

friend_id, friend_follower_id
    0,1
    0,9
    1,47
    1,12
    2,41
    2,66
    2,75
    3,65
    3,21
    3,4
    3,94
    4,64
    4,32

如何在给定的friend_id_a和order_k找到与friend_id_a相隔k度的用户的情况下构建查询?

这是我的初始查询文件的样子:

create or replace function degree6
 (friend_id_a in integer, order_k in integer)
return sys_refcursor as crs sys_refcursor;

我正在寻找任何可以让我开始并最终到达输出的帮助或资源。

更新: 输出将是除了friend_id_a之外k度的其他朋友的列表。

定义A的order-k跟随者B,使得B不是A,并且: 1.如果k = 0,那么A是A的唯一0阶跟随者。 2.如果k = 1,那么A的追随者是A的1号粉丝。 3.如果k> 1;那么对于i = 0到k-1,B不是A的顺序跟随者;而B是追随者 A的顺序 - (k-1)跟随者

感谢。

2 个答案:

答案 0 :(得分:1)

您可以按级别和friend_id构建分层查询和过滤器。例如,在3级获得用户0的所有朋友:

SELECT friend_id, friend_follower_id, level
FROM friends
WHERE LEVEL = 3
CONNECT BY PRIOR friend_follower_id = friend_id
START WITH friend_id = 0

答案 1 :(得分:0)

在Oracle 11gR2或更高版本上,我们可以使用递归子查询因子语法来执行此操作。

with friends (id, follower, lvl) as
    ( select friend_id, friend_follower_id, 1
      from   friendgraph
      where  friend_id = 0
      union all
      select fg.friend_id, fg.friend_follower_id, f.lvl + 1
      from   friendgraph fg
             join
             friends f
             on (fg.friend_id = f.follower)
      where f.lvl + 1 <= 3
    )
select *
from   friends
/

这是在带有Ref Cursor的函数中实现它的一种方法:

create or replace function degree6
     (friend_id_a in integer
       , order_k in integer)
    return sys_refcursor
is
    return_value sys_refcursor;
begin
    open return_value for
        with friends (id, follower, lvl) as
        ( select friend_id, friend_follower_id, 1
          from   friendgraph
          where  friend_id = friend_id_a
          union all
          select fg.friend_id, fg.friend_follower_id, f.lvl + 1
          from   friendgraph fg
            join
              friends f
              on (fg.friend_id = f.follower)
          where f.lvl + 1 <= order_k
        )
        select *
        from   friends;
    return return_value;
end degree6;
/

在SQL * Plus中使用它:

SQL> var rc refcursor
SQL> exec :rc :=  degree6(0,3)

PL/SQL procedure successfully completed.

SQL> print rc

        ID   FOLLOWER        LVL
---------- ---------- ----------
         0          1          1
         0          9          1
         1         12          2
         1         47          2

SQL>