2012-04-29 39 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的平方。如果你有很多用戶,這對你的數據庫來說可能有很多工作要做。