我有以下表格:
members(id, name, surname, username, password)
friends(uid, friend_uid, confirmed_uid, confirmed_friend_uid)
朋友表中的 uid
和friend_uid
与members.id
相关,其中uid
始终低于friend_uid
。当friends.confirmed
同意成为朋友时friends.uid
为真,friends.friend_confirmed
确认友情时friends.friend_uid
为真。
用户A只是B和C的朋友,他们都确认了友谊。我想要一个查询,显示一个B和C的列表(所有已确认的朋友)确认的朋友,他们不是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。希望它通过单个查询清楚地展示了我的目标。
答案 0 :(得分: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 */
在选择列表中,选择所需字段
答案 1 :(得分:0)
看了subquery documentation后,我设法提出了一个有效的解决方案。
在此示例中,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的朋友。它还确保两个成员在关系中确认了友谊。
可能有办法减少此查询的大小,因为整个查询中三个不同的场合使用相同的subquery。
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
如果有办法只运行一次子查询,请告诉我。否则,如果/当我自己弄明白时,我会编辑答案。