-2

我有以下表格:

members(id, name, surname, username, password)
friends(uid, friend_uid, confirmed_uid, confirmed_friend_uid)

在friends表中uidfriend_uid相关的members.id,哪里uid总是更低friend_uid。同意成为朋友friends.confirmed时为真,确认友谊时为真。friends.uidfriends.friend_confirmedfriends.friend_uid

用户 A 只是 B 和 C 的朋友,他们都确认了友谊。我想要一个查询,它将向 A 显示 B 和 C 的列表(所有 A 的已确认朋友)已确认的尚未与 A 成为朋友的朋友。确保如果 B 和 C 有共同的朋友,他们是列表的顶部。

由于我的 MySQL 非常生锈,我目前正在使用多个查询来执行此操作,但这一定是非常低效的,我需要在它开始影响我的网站性能之前为我创建一个查询。

我已经开始阅读 MySQL 文档,如果我有任何地方我会更新它,但是如果有人可以帮助我加快这个过程,我将不胜感激。

这是我用一些伪代码来做的:

member_id_for_A = 1;
friends_of_A = mysql_query("
            SELECT m.*, f.* FROM friends f 
            inner join members m on m.id = f.uid 
              WHERE f.friend_uid = " + member_id_for_A + " AND confirmed_uid=1 AND confirmed_friend_uid=1 
            UNION
              SELECT m.*, f.* FROM friends f 
              inner join members m on m.id = f.friend_uid 
                WHERE f.uid = " + member_id_for_A + " AND confirmed_uid=1 AND confirmed_friend_uid=1");

foreach(row : friends_of_A)
{
  friend_id = get_friened_id(row, member_id_for_A);
  friends_of_friend = get_friends(friend_id); // Performs a query like above friends_of_friend
  result = remove_matches(friends_of_A, friends_of_friend); // Remove common friends

  // Do something with results and move onto the next friend
}

我知道这是非常糟糕的代码并且效率不高,但这是一种快速的 hacky 方式,我可以获得所需的功能,直到我有时间学习更多 MySQL。希望它可以通过一个查询清楚地说明我的目标。

4

2 回答 2

0

干得好...

select m.id,m.surname,m.name from friends f1
inner join friends f2
on f1.friend_uid=f2.uid      /* Identify friend of friend*/
inner join members m
on m.id=f2.friend_uid       /* Match & get Friend of Friend's User detail */
where f1.confirmed_uid=1         /* Friend1 is confirmed */
and f2.confirmed_friend_uid=1
and m.id <> f2.uid          /* Friend2 is not already a friend */

在选择列表中,选择您的必填字段

于 2012-11-24T11:34:06.753 回答
0

在查看了子查询文档后,我设法提出了一个可行的解决方案。

在这个例子中,A 有一个members.id=8.

SELECT * FROM members
WHERE id IN ( 
 SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.uid 
 WHERE f.friend_uid IN ( 
  SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.uid 
  WHERE f.friend_uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1  
   UNION SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.friend_uid 
   WHERE f.uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1
 ) AND m.id<>8 AND f.confirmed_uid=1 AND f.confirmed_friend_uid=1 
  UNION SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.uid 
  WHERE f.uid IN ( 
   SELECT m.id FROM friends f INNER JOIN members m on m.id=f.uid 
   WHERE f.friend_uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1 
    UNION SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.friend_uid
    WHERE f.uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1
   ) AND m.id<>8 AND f.confirmed_uid=1 AND f.confirmed_friend_uid=1
) AND id NOT IN (
 SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.uid 
 WHERE f.friend_uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1  
  UNION SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.friend_uid 
  WHERE f.uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1
); 

此查询运行良好且快速,并返回 A 的所有朋友的朋友,这些朋友还不是 A 的朋友。它还确保关系中的两个成员都确认了友谊。

很可能有一种方法可以减小此查询的大小,因为在整个查询中的三个不同场合都使用了相同的子查询。

 SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.uid 
 WHERE f.friend_uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1  
  UNION SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.friend_uid 
  WHERE f.uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1

如果有办法只运行这个子查询一次,请告诉我。否则,如果/当我自己弄清楚时,我会编辑答案。

于 2012-11-26T14:23:32.133 回答