【问题标题】:Oracle SQL how to write a sql statement that verifies if user in my network( ie friends or friend of friends)Oracle SQL如何编写验证用户是否在我的网络中的sql语句(即朋友或朋友的朋友)
【发布时间】:2010-02-19 13:05:11
【问题描述】:

我有这个问题。给定一个包含用户在社交网络中的用户名的 users 表和包含用户名和用户名的 friends 表,如下所示...

username friendname

John        Thomas
Chris       James

...如果用户在我的网络中,我正在尝试编写一个 SQL 语句。换句话说 该用户是朋友还是朋友的朋友?

我一直在解决这个问题,只能提出这个问题:

SELECT f2.username, f2.friendname 
FROM friends f2 
WHERE f2.username IN (
      SELECT f1.friendname 
      FROM friends f1 
      WHERE f1.username = 'Thomas') 
AND f2.friendname <> 'user1' 
AND f2.friendname = 'user2';    

它基本上检查用户是否是我朋友的朋友,即如果为假,则返回 null。

试图弄清楚如何扩展以通过我所有的朋友网络。我的意思不仅仅是我朋友的朋友。

【问题讨论】:

    标签: sql oracle social-networking


    【解决方案1】:
    SELECT  *
    FROM    (
            SELECT  username
            FROM    friends
            START WITH
                    username = 'myname'
            CONNECT BY
                    friendname = PRIOR username
                    AND level <= 3
            )
    WHERE   username = 'friendname'
            AND rownum = 1
    

    根据需要更新关卡:可以搜索第三层好友等

    如果友谊关系是对称的,你应该做如下查询:

    WITH    q AS
            (
            SELECT  username, friendname
            FROM    friends
            UNION ALL
            SELECT  friendname, username
            FROM    friends
            ),
            f AS
            (
            SELECT  friendname, level
            FROM    q
            START WITH
                    username = 'Thomas'
            CONNECT BY NOCYCLE
                    username = PRIOR friendname
            )
    SELECT  *
    FROM    f
    WHERE   friendname = 'Jo'
            AND rownum = 1
    

    如果你对你的表进行非规范化,这个查询会变得更快:每个友谊存储两条记录,如下所示:

    CREATE TABLE dual_friends (orestes NOT NULL, pylades NOT NULL, CONSTRAINT pk_dualfriends_op PRIMARY KEY (orestes, pylades)) ORGANIZATION INDEX
    AS
    SELECT  username, friendname
    FROM    friends
    UNION ALL
    SELECT  friendname, username
            FROM    friends
    

    那么你可以把上面的CTE换成dual_friends

    WITH    f AS
            (
            SELECT  pylades, level
            FROM    dual_friends
            START WITH
                    orestes  = 'Thomas'
            CONNECT BY NOCYCLE
                    orestes = PRIOR pylades
                    AND level <= 3
            )
    SELECT  *
    FROM    f
    WHERE   pylades = 'Jo'
            AND rownum = 1
    

    ,这将使用索引并且效率更高,特别是如果您将级别限制在某个合理的值。

    【讨论】:

    • 然而 oracle 有使用 connect by 的层次查询,所以会为你做级别搜索
    • 那个 sql 似乎对我有用。好的,假设给定这个表的用户名friendname Thomas Alice Alice Bob Bob Jo 用myname = Thomas 和friendname ='Jo' 运行该sql 没有给出任何指示Jo 不在Thomas 网络中,这是不正确的
    • @user:你们的友谊关系是对称的吗?也就是说,如果AliceThomas 的朋友,那么Thomas 也是Alice 的朋友吗?我相信他是,但最好指定它。
    • @Quassnoi,你想试试你对这个示例表的查询用户名friendname Thomas Alice Alice Bob Bob Jo 它似乎什么也没返回,不确定是不是我
    • @Quassnoi,我实际上设法使用您以前的一些建议和调整以及谷歌搜索使其工作。但是这个新的虽然打败了它,看起来我还有很多东西要学。谢谢你的一切
    【解决方案2】:

    你可以使用connect by

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-10
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多