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

Posted

技术标签:

【中文标题】用pl/sql计算6度分离度的算法和查询?【英文标题】:Algorithm and query for calculating 6 - degree of separation with pl/sql? 【发布时间】:2015-04-17 04:24:13 【问题描述】:

我有一个名为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 的第 i 阶跟随者; B是追随者 A的一个订单-(k-1)个追随者

谢谢。

【问题讨论】:

什么是分离度?你能用提供的数据举个例子吗? 我发布了有关问题的更新。 有关算法帮助,请查看此已回答的帖子:[此处][1] [1]:***.com/questions/2076715/… 我看到了,但不是很明白。 【参考方案1】:

您可以构建分层查询并按级别和朋友 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

【讨论】:

我不熟悉分层查询,所以我不明白这段代码在做什么。此递归是否存在退出条件? 是的,通过这个查询,您正在构建一棵树,其根的 id 为 0,所有的追随者都是孩子。使用 CONNECT BY 子句,您是在说父母和孩子的关联方式(friend_id - follower_id),即 id 为“friend_follower_id”的行是具有某个“friend_id”的行的子节点。 LEVEL 关键字告诉您离根有多远 - 您正在寻找的程度 - 基本上,通过该查询,您将使用 CONNECT BY PRIOR friend_follower_id =friend_id 子句连接父行和子行。 您可以在以下位置找到更多信息:docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm【参考方案2】:

在 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> 

【讨论】:

以上是关于用pl/sql计算6度分离度的算法和查询?的主要内容,如果未能解决你的问题,请参考以下文章

测量两个短音频相似度的最简单算法

语义相似度相关文章链接

余弦相似度的 SQL 计算

计算图像相似度的算法都有哪些

余弦相似度的应用

PL SQL:查询以计算字段的不同值