基本上我要做的是根据共同的兴趣来建议人。
我有一个用户表。
我有一个Interested_People表,其中存储了UserID + InterestID。
我有一个联系人列表,其中存储了彼此相加的人。
我想要的只是输出不是你朋友的人。
我在互联网上搜索了很多但却找不到这样的东西。
虽然我创建了一个查询,但速度非常慢。现在我请求你们,如果你可以稍微编辑我的查询,并使其更多带宽&时间有效。
SELECT *
FROM users
WHERE id IN(SELECT userid
FROM interested_people
WHERE interested_in IN(SELECT interested_in
FROM interested_people
WHERE userid = [userid])
AND id NOT IN(SELECT user1 AS my_friends_userid
FROM contactlist f
WHERE f.user2 = [userid]
AND accepted = 1
UNION
SELECT user2 AS my_friends_userid
FROM contactlist f
WHERE f.user1 = [userid]
AND accepted = 1))
AND id != [userid]
ORDER BY Rand ()
LIMIT 0, 10;
此查询实际上完成了这项工作,但在本地计算机中需要很长时间约16秒。那不是我想要的。我想要一个快速可靠的人。
提前致谢!
答案 0 :(得分:1)
WHERE子句中的子查询在MySQL中通常很慢;至少比可比的JOIN慢。
SELECT others.*
FROM interested_people AS userI
INNER JOIN interested_people AS othersI
ON userI.interestid = othersI.interestid
AND userI.userid <> othersI.userid
INNER JOIN users AS others ON othersI.user_id = others.userid
LEFT JOIN contactlist AS cl
ON userI.userid = cl.user1
AND others.userid = cl.user2
AND cl.accepted = 1
WHERE userI.userid = [userid]
AND cl.accepted IS NULL
ORDER BY RAND()
LIMIT 0, 10;
注意:直觉让我想知道联系人列表可能更好地作为where子查询。
AND cl.accepted IS NULL
最终在JOIN之后处理,导致只允许在联系人列表中没有匹配的结果。
如果你想进一步提升一点:
SELECT others.*, COUNT(1) AS interestsCount
...
GROUP BY others.userid
ORDER BY interestsCount DESC, RAND()
LIMIT 0,10;
这会让您随机选择最有共同兴趣的人。
答案 1 :(得分:1)
首先,查看您感兴趣的查询并假设“userID” 你正在测试is = 1.听起来你正试图获得一个级别 远离那些用户1也对...感兴趣。
SELECT userid FROM interested_people
WHERE interested_in IN
( SELECT interested_in FROM interested_people
WHERE userid = [userid] )
Interested_People的示例数据
userID Interested_In
1 5
1 7
1 8
2 3
2 5
2 7
7 1
7 2
7 5
8 3
在这种情况下,最内层返回interest_in值为5,7,8。 然后,让所有对5,7和8感兴趣的用户返回2和7。 (但由于用户2和7都对5感兴趣,因此2 ID将返回TWICE 因此可能会在以后重复加入。我会做的很明显。这都儿一样 结果可以使用以下查询完成,您可以使用...
进行采样SELECT distinct ip2.userid
from
interested_people ip
join interested_people ip2
ON ip.interested_in = ip2.interested_in
where
userid = [parmUserID]
现在,您需要从此列表中排除已接受的所有联系人。 然后,您可以左键连接两次以进行联系,并确保为NULL 表示没有其中一个联系人...然后再次加入到用户表中 获取用户详细信息。
SELECT
u.*
from
users u
JOIN
( SELECT distinct
ip2.userid
from
interested_people ip
join interested_people ip2
ON ip.interested_in = ip2.interested_in
left join contactList cl1
ON ip2.userid = cl1.user1
AND cl1.accepted = 1
left join contactList cl2
ON ip2.userid = cl2.user2
AND cl2.accepted = 1
where
ip.userid = [parmUserID]
AND NOT ip2.userID = [parmUserID] ) PreQuery
ON u.id = PreQuery.userID
order by
RAND()
limit
0, 10
我会在你的contactList表上有两个索引来优化左连接... user1和user2在主要位置......同样对于interested_people表。
table index
contactList ( user1, accepted )
contactList ( user2, accepted )
interested_people ( userid, interested_in )
interested_people ( interested_in, userid )
我希望您的用户表已经在ID上作为主键索引。
答案 2 :(得分:0)
我认为这会给你相同的结果,但表现更好:
SELECT * FROM Users u
INNER JOIN interested_people i
ON u.id = i.userid
WHERE NOT EXISTS
(SELECT * FROM contacts WHERE user1 = [userid] or user2 = [userid] and accepted=1)
AND id != [userid]
ORDER BY Rand()
LIMIT 0, 10
如果合理,请跳过ORDER BY子句。那将是最昂贵的部分
select和join子句为您提供了对连接感兴趣的用户,而WHERE NOT EXISTS是一种高效的方法来排除已列出的联系人。