創建一個表,然後插入測試數據:由book_id
CREATE TABLE `ub` (
`user_id` int(11) NOT NULL,
`book_id` varchar(10) 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'), (1, 'B'), (1, 'C');
insert into ub values (2, 'A'), (2, 'B'), (2, 'C'), (2,'D');
insert into ub values (3, 'X'), (3, 'Y'), (3, 'C'), (3,'Z');
insert into ub values (4, 'W'), (4, 'Q'), (4, 'C'), (4,'Z');
加入測試數據到自身上,並創建一個臨時表來保存每個USER_ID和它在共同與目標USER_ID的圖書數量:
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
where target.user_id = 1
group by similar.user_id;
select * from ub_rank;
+---------+------+
| user_id | rank |
+---------+------+
| 2 | 3 |
| 3 | 1 |
| 4 | 1 |
+---------+------+
3 rows in set (0.00 sec)
我們可以看到,USER_ID有共同3 USER_ID 1,但user_id說明3和4的user_id僅各有1。
接下來,選擇所有的臨時表的用戶具有不匹配目標USER_ID的書冊,並安排秩這些。請注意,同一本書可能出現在不同的用戶列表中,因此我們總結每本書的排名,以便常用書獲得更高的排名。
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
where target.book_id is null
group by similar.book_id
order by total_rank desc;
+---------+------------+
| book_id | total_rank |
+---------+------------+
| D | 3 |
| Z | 2 |
| X | 1 |
| Y | 1 |
| Q | 1 |
| W | 1 |
+---------+------------+
6 rows in set (0.00 sec)
Z書出現在兩個用戶列表中,所以排在X,Y,Q,W之上,它只出現在一個用戶列表中。圖書d做最好的,因爲它出現在USER_ID 2的名單,其中有與目標USER_ID 1
哇共同3個項目,這是一個非常全面的迴應。非常感謝你! – 2010-04-23 13:16:20
這是一個令人難以置信的答案,一直使用這個修改後的版本爲我的網站和它的工作如此出色。 – Franco 2014-07-25 22:50:22