2012-04-29 43 views
3

我正在创建一个音乐网站,我希望用户能够找到喜欢与他们大致相同的艺术家的用户。比较两个结果集之间的相似性

我有一个'喜欢'表有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 

这些用户的共同点4名艺术家。 有没有办法比较这2个结果集,找到数据库中最相似的人?

我的第一个想法是在一个字符串中连接喜欢:“12,13,14,26,42,44”,并使用mysql FULLTEXT分数比较不同的字符串。 这没有奏效......不知道为什么,但mysql全文仅适用于文本...不能用数字...

任何想法或任何线索将不胜感激。

回答

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 | 
+---------+---------+---------------+ 
+0

感谢您的帮助,您的查询就像一个chram :) – MonsieurNinja

+0

@sikko高兴地帮助!与你的项目祝你好运:) –

0

,能够加入一个表到其自身。 (您需要为表的两个“副本”中的至少一个指定别名,以便您的查询不含糊)。

因此,给定两个用户,您可以找到他们共有的“喜欢”通过将like表加入其自身。您还可以通过进行左连接来查找用户2共享用户1喜欢的比例,并计算出有多少结果以及有多少结果为空。请注意,这不是对称操作,您需要解决其中一个或两个数字都为0的情况。

当您说“要找到数据库中最相似的人”时:您可以对每一对用户都这样做,但请注意,如果您有n用户,那么这需要执行n*(n-1)/2比较,该比较大约为n的平方。如果你有很多用户,这对你的数据库来说可能有很多工作要做。