朋友两次表现出同样的关系

时间:2011-08-05 14:25:07

标签: mysql sql database relational-database

我正在建立一个饲料系统ala facebook只是为了它的乐趣和训练,但我提出了一个有趣的问题。想象一下这种情况:

我是nr1,nr2和nr3的朋友。在我的数据库中,它也是数据库中的用户,nr4,我不是他的朋友。所以,请说nr1 befriend nr4,在这种情况下,我希望我的feed更新nr1是nr4的朋友。这基本上不是很难做到(至少要让它起作用,我不会对性能有所了解:P)。 然后nr1与nr2成为朋友,但这与nr2 befriend nr1相当,这就是我的问题。

我的友谊数据库以一个友谊生成两个记录的方式工作。我读过这通常是更快的方法。

友谊表:

  • USER_ID
  • friend_id
  • 未决
  • lastchange

用户表:

  • USER_ID
  • USER_NAME

我想出了以下代码:

SELECT
    u1.user_id AS friend_id,
    u1.user_name SA friend_name,
    u2.user_id AS friends_friend_id,
    u2.user_name AS friends_friend_name
FROM users AS u1
JOIN friendship AS f1
    ON u1.user_id = f1.friend_id
    && f1.user_id = {$user_id}
    && f1.friend_pending = 0
JOIN friendship AS f2
    ON u1.user_id = f2.user_id
    && f2.friend_pending = 0
JOIN users AS u2
    ON f2.friend_id = u2.user_id
WHERE TIMESTAMPDIFF(SECOND, f2.lastchange, '{$last_login}' ) < 0;

Okey这基本上做的是它让我所有的朋友与我上次登录后与其他人交朋友。唯一的问题是,如果我是两个相互交朋友的朋友,将在此查询中选择他们两个。 差异(这使得无法使用SELECT DISTINCT)是这样的;

  • 第一次nr1将成为朋友而nr 2将成为朋友的朋友

  • 第二次nr2将成为朋友而nr1将成为朋友的朋友。

我不希望这样,我希望每个关系有一行。

你们有任何想法如何解决这个问题?我提出的任何解决方案都没有显示任何内容:(

谢谢!

第一次编辑:我刚刚提出了另一个与此问题相关的问题。在phpMyAdmin中,上面生成了一个包含4列的正确表。但是在php(或者更确切地说是codeigniter的查询函数)中,它只显示了两列,但是添加了更多的行...这最终我不知道谁是谁...

再次

第二次编辑:Okey我刚刚解决了我在第一次编辑中提出的问题,我只是用AS重命名了这些列。你仍然有主要问题。

第3次修改:Stevie G正在请求一些示例数据,这是查询结果:

friend_id  |  friend_name  |   friends_friend_id  |  friends_friend_name
    1             nr1                  4                   nr4
    1             nr1                  2                   nr2     
    2             nr1                  1                   nr2

如果你关注我的小故事,这就是我得到的。 id = 1不是“我”,而是另一个用户

第4次修改不幸的是,我觉得我还不够清楚。我最想得到的是一个数组,其中每个元素包含:

  • friend_id
  • FRIEND_NAME
  • friends_friend_id
  • friends_friend_name

就像编辑3中的示例数据一样,除了我之前的名字可能会误导你... 所以我的问题是,正如你可以看到编辑3,如果我的两个朋友成为朋友,我会得到两行为一个关系。我想得到的是:

friend_id  |  friend_name  |   friends_friend_id  |  friends_friend_name
    1             nr1                  2                   nr2     
    2             nr1                  1                   nr2

我希望自己更清楚!感谢

4 个答案:

答案 0 :(得分:0)

所以对我而言,看起来你的要求是不完整的,因为在朋友提要中,如果nr2和nr1相互交朋友,你想要:

  1. 看到的内容是“你的共同朋友nr2和nr1彼此友好!”
  2. 看到的内容是“你的朋友nr2与朋友保持联系!”基于谁先实现了友谊。
  3. 情景#1

    如果您的朋友的朋友也在您的朋友中,您需要另一个联接检查,如果是,则返回名为AlsoMyFriend的布尔列。然后,如果也是友谊朋友是1,则返回“你的共同朋友彼此友好”,否则返回正常的“你的朋友会成为新朋友。”

    或者,您可以在代码中执行此操作,只需检查朋友的朋友ID是否在朋友的ID列表中,然后根据该ID翻转您的Feed语句。

    情景#2

    友谊表* primary_mover *中添加一列,并将该值设置为启动友谊的* user_id *。在查找朋友的朋友时,可以过滤*,其中primary_mover = user_id *仅获得1个双边关系。

    作为一个简单的衡量标准,你可以简单地添加一个过滤器,只说朋友的朋友ID大于朋友的ID:

    SELECT
        u1.user_id AS friend_id,
        u1.user_name SA friend_name,
        u2.user_id AS friends_friend_id,
        u2.user_name AS friends_friend_name
    FROM users AS u1
    JOIN friendship AS f1
        ON u1.user_id = f1.friend_id
        && f1.user_id = {$user_id}
        && f1.friend_pending = 0
    JOIN friendship AS f2
        ON u1.user_id = f2.user_id
        && f2.friend_pending = 0
        && f2.friend_id > f2.user_id -- pulls nr1 befriending nr2, not nr2 befriending nr1
    JOIN users AS u2
        ON f2.friend_id = u2.user_id
    WHERE TIMESTAMPDIFF(SECOND, f2.lastchange, '{$last_login}' ) < 0;
    

答案 1 :(得分:-1)

您尝试使用

吗?
SELECT DISTINCT

答案 2 :(得分:-2)

这是一个棘手的问题,但是,试试这个:

SELECT  --Select your user details, and your direct friends details
    u1.user_id UserId,
    u1.user_name UserName,
    u2.user_id FriendsUserId,
    u2.user_name FriendsUserName
FROM users AS u1
JOIN friendship AS f1
    ON u1.user_id = {$user_id}
    && f1.friend_pending = 0
JOIN users AS u2
    ON f1.friend_id = u2.user_id
JOIN friendship AS f2
    ON f1.friend_id = f2.userid
    && f2.friend_pending = 0
WHERE TIMESTAMPDIFF(SECOND, f2.lastchange, '{$last_login}' ) < 0;
UNION 
SELECT  --Select your user details, and your friends friends details
    u3.user_id UserId,
    u3.user_name UserName,
    u4.user_id FriendsUserId,
    u4.user_name FriendsUserName
FROM users AS u3
JOIN friendship AS f3
    ON u3.user_id = {$user_id}
    && f3.friend_pending = 0
JOIN friendship AS f4
    ON f3.friend_id = f4.user_id
    && f4.friend_pending = 0 
JOIN users AS u4
    ON f3.friend_id = u4.user_id
WHERE TIMESTAMPDIFF(SECOND, f4.lastchange, '{$last_login}' ) < 0;

假设结果与我认为的结果一样,UNION应该过滤掉dupes,因为u1.user_id应该始终是你的user_id ..

答案 3 :(得分:-2)

尝试

SELECT     
    u1.user_id AS friend_id,     
    u1.user_name SA friend_name,     
    u2.user_id AS friends_friend_id,     
    u2.user_name AS friends_friend_name 
FROM users AS u1 
JOIN friendship AS f1     
    ON u1.user_id = f1.friend_id     
     && f1.user_id = {$user_id}     
     && f1.friend_pending = 0 
JOIN friendship AS f2     
    ON u1.user_id = f2.user_id     
     && f1.user_id <> f2.friend_id 
     && f2.friend_pending = 0 
JOIN users AS u2     
     ON f2.friend_id = u2.user_id 
WHERE TIMESTAMPDIFF(SECOND, f2.lastchange, '{$last_login}' ) < 0;