我正在创建一个音乐网站,我希望用户能够找到喜欢与他们大致相同的艺术家的用户。
我有一个'like'表有2列'id_user','id_artist'。 以下是我希望如何工作的示例:
User 1 likes:
1, 12
1, 13
1, 14
1, 26
1, 42
1, 44
User 2 likes:
2, 13
2, 14
2, 15
2, 26
2, 42
2, 56
这2位用户共有4位艺术家。 有没有办法比较这两个结果集,找到数据库中最相似的人?
我的第一个想法是以这种方式连接喜欢:字符串中的“12,13,14,26,42,44”,并使用mysql FULLTEXT分数来比较不同的字符串。 那不起作用......不知道为什么但是mysql全文只适用于文本...而不是数字......
任何想法或任何线索都会非常感激。
答案 0 :(得分:2)
这样的事情:
SELECT first_user.id_user, second_user.id_user, COUNT(first_user.id_user) AS total_matches
FROM likes AS first_user
JOIN likes AS second_user
ON second_user.id_artist = first_user.id_artist
AND second_user.id_user != first_user.id_user
GROUP BY first_user.id_user, second_user.id_user
ORDER BY total_matches DESC
LIMIT 1
请注意,这不是很有效。解决此问题的一种方法是创建一个“缓存表”,其中包含删除了LIMIT 1
部分的此查询的输出。添加一些相关索引并查询此缓存表。您可以设置一个cron作业来定期更新此表。
示例:
CREATE TABLE IF NOT EXISTS `likes` (
`id_user` varchar(50) DEFAULT NULL,
`id_artist` varchar(50) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `likes` (`id_user`, `id_artist`) VALUES ('8', '39'), ('8', '37'), ('4', '37'), ('8', '24'), ('8', '7'), ('4', '28'), ('8', '28'), ('4', '27'), ('4', '11'), ('8', '49'), ('4', '7'), ('4', '40'), ('4', '29'), ('8', '22'), ('4', '29'), ('8', '11'), ('8', '28'), ('4', '7'), ('4', '31'), ('8', '42'), ('8', '25'), ('4', '25'), ('4', '17'), ('4', '32'), ('4', '46'), ('4', '19'), ('8', '34'), ('3', '32'), ('4', '21')
+---------+---------+---------------+
| id_user | id_user | total_matches |
+---------+---------+---------------+
| 8 | 4 | 7 |
+---------+---------+---------------+
答案 1 :(得分:0)
可以将表连接到自身。 (您需要为表的两个“副本”中的至少一个指定别名,以便您的查询不明确。)
因此,给定两个用户,您可以通过将like
表连接到自身来找到他们共同的“喜欢”。您还可以通过执行左连接并计算有多少结果和多少为空来查找用户2共享用户1喜欢的比例。请注意,这不是对称操作,您需要解决其中一个或两个数字为0的情况。
当您说“要在数据库中找到最相似的人”时:您可以为每对用户执行此操作,但请注意,如果您有n
个用户,那么这涉及执行{{1}比较,大约为n*(n-1)/2
平方。如果你有很多用户,那么你的数据库可能需要做很多工作。