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

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

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

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

4

2 回答 2

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 |
+---------+---------+---------------+
于 2012-04-29T20:14:23.170 回答
0

可以将表连接到自身。(您需要为表的两个“副本”中的至少一个指定别名,这样您的查询就不会模棱两可。)

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

当您说要“在数据库中找到最相似的人”时:您可以为每一对用户执行此操作,但请注意,如果您有n用户,则这涉及进行n*(n-1)/2比较,这是n平方的顺序。如果您有很多用户,这可能是您的数据库要做的大量工作。

于 2012-04-29T20:16:55.027 回答