2013-03-26 43 views
1

通過參考Collaborative filtering in MySQL?,我創建了下面的:EDITED尋找SQL改進

CREATE TABLE `ub` (
    `user_id` int(11) NOT NULL, 
    `book_id` varchar(10) NOT NULL, 
    `rate` int(11) NOT NULL, 
    PRIMARY KEY (`user_id`,`book_id`), 
    UNIQUE KEY `book_id` (`book_id`,`user_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

insert into ub values (1, 'A', '8'), (1, 'B', '7'), (1, 'C', '10'); 
insert into ub values (2, 'A', '8'), (2, 'B', '7'), (2, 'C', '10'), (2,'D', '8'), (2,'X', '7'); 
insert into ub values (3, 'X', '10'), (3, 'Y', '8'), (3, 'C', '10'), (3,'Z', '10'); 
insert into ub values (4, 'W', '8'), (4, 'Q', '8'), (4, 'C', '10'), (4,'Z', '8'); 

然後,我抽到了下表,瞭解它是如何工作的。

create temporary table ub_rank as 
select similar.user_id,count(*) rank 
from ub target 
join ub similar on target.book_id= similar.book_id and target.user_id != similar.user_id and target.rate= similar.rate 
where target.user_id = 1 
group by similar.user_id; 

select * from ub_rank; 

+---------+------+ 
| user_id | rank | 
+---------+------+ 
|  2 | 3 | 
|  3 | 1 | 
|  4 | 1 | 
+---------+------+ 

但是,我開始在下面的代碼後感到困惑。

select similar.rate, similar.book_id, sum(ub_rank.rank) total_rank 
from ub_rank 
join ub similar on ub_rank.user_id = similar.user_id 
left join ub target on target.user_id = 1 and target.book_id = similar.book_id and target.Rate= similar.Rate 
where target.book_id is null 
group by similar.book_id 
order by total_rank desc, rate desc; 

+---------+------------+ 
| book_id | total_rank | 
+---------+------------+ 
| X  |   4 | 
| D  |   3 | 
| Z  |   2 | 
| Y  |   1 | 
| Q  |   1 | 
| W  |   1 | 
+---------+------------+ 

(已解決)首先,我想知道X和D的總排名爲什麼不相同(即3)。是不是統計與用戶A相同的用戶B的書籍數量?那麼,D和X應該是3?!其次,我應該如何修改代碼,比如速率可以作爲排名的一個元素。也就是說,如果兩本書的排名相同,那麼分數越高的排名就越高。

由於

EDITED

(1, 'A', '8'),(1, 'B', '7'),(1, 'C', '10' ); (2,'B','7'),(2,'C','10'),(2,'D','8'), ),(2,'X','7');

我想要做的是,假設用戶1和2有類似的行爲(選擇A,B,C之前與匹配的評級),因此我會向用戶A推薦D,因爲它有更高的比率。

似乎上面的代碼不這樣做?因爲,排名第一的是X.

回答

1

首先,我想知道X和D的總排名爲什麼不相同(即 3)。用戶B的 是否與用戶A相同的書數?那麼,D和X應該是3?!

X有一個更大的排名作爲其本作的第二user_id和第三user_id,查詢得到的總排名的,在這種情況下3 (user_id = 2) + 1 (user_id = 3)

二,我應該怎麼修改代碼例如費率可以充當排名的 元素。也就是說,如果兩本書的排名相同,則 那麼標記較高的排名將會排在更高的排名。

使用的速度遞減相同的查詢,並責令軍銜後,像

select similar.book_id, sum(ub_rank.rank) total_rank 
from ub_rank 
join ub similar on ub_rank.user_id = similar.user_id 
left join ub target on target.user_id = 1 and target.book_id = similar.book_id and target.Rate= similar.Rate 
where target.book_id is null 
group by similar.book_id 
order by total_rank desc, rate desc; 

更新:根據您的要求,您需要的是具有與最接近的書籍列表中得到比賽與其他用戶,並具有最大的價格,嘗試下面的查詢相同

SELECT 
    temp.book_id, 
    temp.rate as book_rate 
FROM (
     SELECT 
      similar.user_id, 
      COUNT(similar.book_id) as book_match_count 
     FROM 
      ub target 
      JOIN ub similar ON target.book_id= similar.book_id AND target.user_id != similar.user_id 
     WHERE 
      target.user_id = 1 
     GROUP BY 
      similar.user_id 
    ) AS users_with_book_matches 
JOIN ub temp ON (temp.user_id =users_with_book_matches.user_id AND temp.book_id NOT IN (SELECT book_id FROM ub WHERE ub.user_id = 1)) 
GROUP BY 
    temp.book_id 
ORDER BY 
    users_with_book_matches.book_match_count DESC, 
    temp.rate DESC 
limit 5 

上述查詢得到前5最接近火柴

這裏的SqlFiddle,一定要改變user_id在2個地方,希望這符合你的目的

+0

謝謝,這是有益的。從你的回答中,我想我可能會做錯事。如前所述,我想要做的是假設用戶1和用戶2具有相似的行爲(選擇A,B,C之前的匹配評級),因此我會向用戶A推薦D,因爲它具有較高的費率。但是,在這種情況下,它也將計算用戶3中的一個。你是否有任何想法,應該如何更改代碼? – HUNG 2013-03-26 03:10:42

+0

@HUNG給你SQL插入值,輸出應該是X,因爲它的排名更高,如果你想輸出爲D,你只需要考慮與當前最近的書籍匹配的user_id的排名用戶,你在找這樣的東西嗎? – Akash 2013-03-26 03:20:47

+0

是的,正是我想要做的! – HUNG 2013-03-26 03:23:20