我已经在这个网站上到处找过了,但似乎没有一个是我要找的。他们中的很多人都在谈论Facebook是如何做到的,或者Twitter是如何向粉丝推荐的,但即便如此,他们也没有给出任何直截了当的答案。
所有我发现的都是使用两个用户ID计算共同的朋友。
我希望能够获取登录用户的ID,查看他们的朋友,并通过他们的朋友来计算与登录用户有最多共同朋友的人,以建议人们添加有最多共同朋友的人。
我正在使用PHP和MySQL来实现这一点。我就是不知道该怎么做。
我的友谊桌是这样的:

---------------------------------
| friend1 |  friend2  | pending |
---------------------------------
|    1    |     2     |    0    |
|    2    |     1     |    0    |
|    3    |     1     |    0    |
|    1    |     3     |    0    |
---------------------------------

此表显示用户1是2和3的朋友
2不是3的朋友,而是1的朋友。
所以,如果用户登录到用户id 2,我希望它建议用户id 3,因为他们都是用户id 1的朋友。
到目前为止我所拥有的:
  public function friendList($user_id = null){
    if(!$user_id){
      $user_id = $this->_data->user_id;
    }
    $query = "SELECT friend2 FROM user_friends WHERE pending = 0 AND ((friend1 = ".$user_id.") AND (friend2 IN (SELECT user_id FROM users WHERE active = 1 AND user_id = friend2)))";
    $data = $this->_db->hardquery($query);
    return $data->results();
  }
  public function suggestUsers(){
    $user_id = $this->_data->user_id;
    $my_friends = array();
    $suggest_friends = array();
    foreach($this->friendList() as $friend){
      array_push($my_friends,$friend->friend2);
    }
    foreach($my_friends as $friend_id){
      foreach($this->friendList($friend_id) as $friendOfFriend){
        $friendOfFriend = $friendOfFriend->friend2;
        if(!in_array($friendOfFriend,$my_friends) && $friendOfFriend != $user_id){
          array_push($suggest_friends,$friendOfFriend);
        }
      }
    }
    foreach($suggest_friends as $sgf){
      $sgf = new user($sgf);
      $sgf = $sgf->data();
      echo "<a href=\"#\">".$sgf->display."</a><br>";
    }
  }

它可以工作,列出用户朋友的朋友,但没有添加用户。。。
然而,我不能根据谁的共同朋友最多来分类,我想这是可以的(尽管我想如果可以的话),但这似乎也不是一个非常有效的方法。。
这似乎需要花费大量的资源来浏览用户的所有好友,特别是如果用户添加了几百到一千个好友,并且他们添加了几百到一千个好友,等等。
我对高级SQL不太熟悉,所以我不知道该怎么做。

最佳答案

下面是对1个查询执行此操作的尝试。其思想是选择friend2列表,并将其加入到friend2所在的select中。然后,使用friend1,我们可以返回根据友谊的相关性排序的行,以及与该人是朋友的每个人。

SELECT
    a.friend2,
    COUNT(*) as relevance,
    GROUP_CONCAT(a.friend1 ORDER BY a.friend1) as mutual_friends
FROM
    user_friends a
JOIN
    user_friends b
ON  (
     b.friend2 = a.friend1
     AND b.pending = 0
     AND b.friend1 = LOGGED_IN_USER
    )
WHERE
    a.pending = 0
AND
    a.friend2 != LOGGED_IN_USER
GROUP BY
    a.friend2
ORDER BY
    relevance DESC;

AsqlFiddle example - http://sqlfiddle.com/#!9/3dbf0/3
编辑
在我最初的查询中,我忘记排除已经是GROUP BY好友的任何用户。在不存在友谊的情况下,使用LOGGED_IN_USERLEFT JOIN,这将返回你想要的结果。
SELECT
    a.friend2,
    COUNT(*) as relevance,
    GROUP_CONCAT(a.friend1 ORDER BY a.friend1) as mutual_friends
FROM
    user_friends a
JOIN
    user_friends b
ON  (
     b.friend2 = a.friend1
     AND b.pending = 0
     AND b.friend1 = LOGGED_IN_USER
    )
LEFT JOIN
    user_friends c
ON
    (
     c.friend2 = a.friend2
     AND c.pending = 0
     AND c.friend1 = LOGGED_IN_USER
    )
WHERE
    a.pending = 0
AND
    c.friend1 IS NULL
AND
    a.friend2 != LOGGED_IN_USER
GROUP BY
    a.friend2
ORDER BY
    relevance DESC;

更新sqlFiddle example - http://sqlfiddle.com/#!9/c38b5c/2

10-08 00:34