2015-04-17 73 views
2

我有一個名爲friendgraph(friend_id,friend_follower_id)的表,我想計算給定朋友和給定學位的6度分離度。 表看起來是這樣的:用pl/sql計算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,並且:如果k = 0,則A是A的唯一0級跟隨器。如果k = 1,則A的追隨者是A的追隨者1 3.如果k> 1;那麼對於i = 0到k-1,B不是A的order-i跟隨者;並且B是訂單 - (k-1)追隨者的追隨者 A

謝謝。

+0

什麼是隔離的程度?你能舉出一個提供數據的例子嗎? – Suing

+0

我發佈了一個更新的問題。 – user2512806

+0

的算法的幫助,看看這個回答後:[點擊這裏] [1] [1]:http://stackoverflow.com/questions/2076715/challenge-how-to-implement-an-算法爲六度分離 – Suing

回答

1

您可以按級別和friend_id構建分層查詢和篩選。例如,要得到用戶0所有的朋友處第3級:

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 
+0

我對分層查詢並不熟悉,所以我不明白這段代碼在做什麼。這種遞歸是否存在退出條件? – user2512806

+0

是的,通過這個查詢,你正在構建一棵樹,其根目錄爲id 0,所有的追隨者都是孩子。使用CONNECT BY子句,您說的是父母和孩子相關的方式(friend_id - follower_id),即具有id'friend_follower_id'的行是具有特定'friend_id'的行的子節點。 LEVEL關鍵字告訴你距離根源有多遠 - 你正在尋找的學位 - 基本上,通過該查詢,您可以通過CONNECT BY PRIOR friend_follower_id = friend_id子句連接父母和子行。 – pablomatico

+0

更多信息,請訪問:http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm – pablomatico

0

在甲骨文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光標實現這個的一種方式:

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中使用它*加:

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>