我正在论坛中创建一个朋友系统。
我正在努力弄清楚如何通过共同计数获取用户和订购。
我正在尝试构建一个显示推荐朋友列表的页面。
这是我的表格结构:
users table
-----
user_id | name |
friends table
-----
friend_id | from_id | to_id
以下是正在发生的事情的一个例子。
假设网站中总共有A
,B
,C
,D
,E
,F
= 6个人。
A
,B
,C
是我的朋友。D
和E
又是B
的朋友。D
也是C
的朋友,但E
不 是C
的朋友。< / LI>
F
不是网站上任何人的朋友。因此,从上面的数据看,D
和E
是我的共同朋友(A
)。 F
不 是我的共同朋友。
由于D
是B
和C
的朋友,而E
只是 的朋友 { {1}}:
B
和A
有D
个共同的朋友。2
和A
有E
共同的朋友。1
和A
有F
共同的朋友。现在,如果我想为不是我朋友的人搜索(记住我0
),我可以做以下事情:
A
$myfriends = "2,3"; //putting all my friends in a variable
但它会以SELECT * FROM users WHERE user_id NOT IN( $myfriends )
的形式产生。
如何以user_id ASC
DESC
的顺序进行搜索。 ?
我是mutual_friends
,A
即。 有更多共同朋友的人首先
请有人告诉我该怎么做?我被困在这里很久了。我搜索了很多东西,但无法弄明白。
答案 0 :(得分:6)
此查询将考虑关系的互惠性,因此,如果关系进入&#34;从A到B&#34;则无关紧要。或者&#34;从B到A&#34;,它仍然会返回预期的结果。所以给出这样的表:
CREATE TABLE people
(`id` int, `name` varchar(1))
;
INSERT INTO people
(`id`, `name`)
VALUES
(1, 'A'),
(2, 'B'),
(3, 'C'),
(4, 'D'),
(5, 'E'),
(6, 'F')
;
CREATE TABLE friends
(`id` int, `personId1` int, `personId2` int)
;
INSERT INTO friends
(`id`, `personId1`, `personId2`)
VALUES
(1, 1, 2),
(2, 3, 1),
(3, 2, 4),
(4, 5, 2),
(5, 3, 4)
;
我相信这是按照你的描述设置的:A和B是朋友,A和C是朋友(注意倒置的关系),B和D是朋友,E和B是朋友(另一个倒置关系),和C和D是朋友。
假设您想要的人的身份在@personId:
SELECT StrangerId, COUNT(MutualFriendId) AS TotalMutualFriends
FROM
(SELECT
CASE WHEN f.personId2 = mf.friendId THEN f.personId1 ELSE f.personId2 END AS StrangerId,
CASE WHEN f.personId1 = mf.friendId THEN f.personId1 ELSE f.personId2 END AS MutualFriendId
FROM
(SELECT
CASE
WHEN personId1 = @personId THEN personId2
ELSE personId1
END AS friendId
FROM friends
WHERE personId1 = @personId OR personId2 = @personId) AS mf
INNER JOIN friends f
ON (personId1 != @personId AND personId2 = mf.friendId)
OR (personId1 = mf.friendId AND personId2 != @personId)
) AS totals
GROUP BY StrangerId
ORDER BY TotalMutualFriends DESC;
@personId = 1的结果是:
StrangerId TotalMutualFriends
4 2
5 1
And here is a SQLFiddle进行演示(我无法让它设置变量,因此其中有一个变量)。
答案 1 :(得分:2)
这样的事情,也许是:
Select user_id, friends.to_id, count(friend_of_friend.to_id)
from users left outer join
friends on users.user_id = friends.from_id left outer join
users as friend_user on friends.to_id = friend_user.user_id left outer join
friends as friend_of_friend on friend_user.user_id = friend_of_friend.from_id and friend_of_friend.to_id in (select to_id from friends where from_id = users.user_id)
Group by USER_ID, friends.to_id
Order by 3
为清晰起见编辑: 此查询的逻辑取决于多次连接同一个表。前两个联接非常简单,我们从一个用户表开始,然后加入将每个用户与他们所有朋友联系起来的朋友表。但是我们再次加入用户表,但这次使用“to”列 - 我们正在获取每个朋友的用户信息。由于我们在查询中不能两次使用相同的表名,因此我们给它一个别名“friend_user”。然后我们再次加入friends表,基于friend_user表中的id - 这给了我们每个原始用户的朋友的所有朋友。然后我们限制朋友的朋友,我们使用“Friend_of_friend.to_id in ...”将朋友的朋友与所有原始用户朋友的列表进行比较,我们通过子查询引入 - 该部分只是在括号内的“in”之后。