【问题标题】:Efficient friend suggestion sql query without using php不使用php的高效好友建议sql查询
【发布时间】:2012-10-16 13:16:13
【问题描述】:

我有一个成员表,其中每个站点成员都是唯一的 ID。 例如

id  firstname   secondname  emailaddress    country city    gender  

第二个表是friends表,结构如下

id  meid    friendid    date

我将使用什么查询来根据共同的朋友获取特定用户的朋友建议并进行相应的排序。在我使用 php 循环并收集共同的朋友之前,但随着网站的发展,php 开始出现行为异常并耗尽内存。

这是我使用的功能

//-----------------------------------------------    
function getFriendSuggestions($id)    
{
            $friendids=getFriendIdArray($id);  //returns list of your friends
            $networkids=getNetworkIdArray($id);//returns list of all members in your network(friends and their friends)
            $diff=array_merge(array(),array_diff($networkids,$friendids));
            $diff_mutual=array();
            $diff_mutual_total=array();
            for ($n=0;$n<count($diff);$n++)
            {
                $ff=getFriendIdArray($diff[$n]);
                $mf=array_merge(array(),array_intersect($ff,$friendids));
                $diff_mutual[]=$mf;
                $diff_mutual_total[]=count($mf);
            }
            $diff=array_merge(array(),$diff);
            $diff_mutual=array_merge(array(),$diff_mutual);
            $diff_mutual_total=array_merge(array(),$diff_mutual_total);    
            $w=$diff_mutual_total;
            arsort($w);
            $d=array();
            $dm=array();
            foreach ($w as $key => $value)
            {
                $d[]=$diff[$key];
                $dm[]=$diff_mutual[$key];
            }
            $cv=array($d,$dm);
            return $cv;
}

【问题讨论】:

  • 我猜是基于共同的朋友。
  • 你能张贴桌子结构吗?
  • 朋友的推荐基于第二个朋友圈,即朋友的朋友。因此,您需要选择所有这些朋友,然后查看他们有多少朋友相互当前成员。
  • 是的,这就是我上面发布的函数的作用。问题是当网络变大时效率低下。

标签: php mysql sql


【解决方案1】:

如果有大量此类条目,我们说 B 可能是 A 的朋友

(B, someguy) (someguy, A)

在数据库中,并且没有(B,A)条目。

我们知道用户 A 的 ID 并将其设为 AID。然后我们可以这样做:

SELECT b.meid, COUNT(b.meid) AS incommon
FROM friends AS b
JOIN friends AS a ON (b.friendid = a.meid AND a.friendid = AID)
GROUP BY b.meid ORDER BY incommon DESC;

这将告诉我们 A 的所有“可能的朋友”,包括那些 已经是 A 的朋友。那么我们必须排除他们:

SELECT maybe.meid, maybe.incommon FROM
( SELECT b.meid, COUNT(b.meid) AS incommon
FROM friends AS b
JOIN friends AS a ON (b.friendid = a.meid AND a.friendid = AID)
GROUP BY b.meid ORDER BY incommon DESC ) AS maybe
LEFT JOIN friends AS already ON (maybe.friendid = already.meid AND already.friendid = AID) WHERE already.friendid IS NULL;

然后我们需要填充其余的字段:

SELECT members.firstname, members.secondname, maybe.incommon FROM
( SELECT b.meid, COUNT(b.meid) AS incommon
FROM friends AS b
JOIN friends AS a ON (b.friendid = a.meid AND a.friendid = AID)
GROUP BY b.meid ORDER BY incommon DESC ) AS maybe
LEFT JOIN friends AS already ON (maybe.friendid = already.meid AND already.friendid = AID) 
    JOIN members ON (members.id = maybe.meid)
    WHERE already.friendid IS NULL;

这将返回 AID 的朋友建议,包括每个选择有多少共同点(例如“John Doe(15 个共同朋友)”等)。

【讨论】:

  • 我打算尝试对两个答案进行测试,我会回来投票
【解决方案2】:

你想要“我朋友的朋友,但他们不是我的朋友”

SELECT
  me.id                               AS member_id,
  their_friends.friendid              AS suggested_friend_id,
  COUNT(*)                            AS friends_in_common
FROM
  members        AS me
INNER JOIN
  friends_map    AS my_friends
    ON my_friends.meid = me.id
INNER JOIN
  friends_map    AS their_friends
    ON their_friends.meid = my_friends.friendid
LEFT JOIN
  friends_map    AS friends_with_me
    ON  friends_with_me.meid     = their_friends.friendid
    AND friends_with_me.friendid = me.id
WHERE
  friends_with_me.meid IS NULL
GROUP BY
  me.id,
  their_friends.friendid

【讨论】:

  • 这让我很困惑,他们的朋友?,可以修改为使用朋友表
  • @SirLojik - 我使用了朋友表三次。每次我将它别名为一个新名称。我第一次称它为my_friends,因为它是与members 表中的行相关的朋友列表。下次它与他们的朋友有关,而不是我的,所以我将其别名为their_friends。它是同一张表,但使用了多次,所以给了不同的别名。
  • 其实你的查询有错误。 LEFT JOIN 的“ON”子句是错误的。正确的是: ON friends_with_me.meid = me.id AND friends_with_me.friendid = their_friends.friendid
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
  • 2012-07-30
  • 1970-01-01
相关资源
最近更新 更多