Utwórz tabelę i wstaw dane testowe:
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');
Połącz ze sobą dane testowe według book_id i utwórz tymczasową tabelę do przechowywania każdego identyfikatora użytkownika i liczby książek, które ma on wspólną z docelowym identyfikatorem użytkownika:
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)
Widzimy, że user_id ma 3 wspólne z user_id 1, ale user_id 3 i user_id 4 mają tylko po 1.
Następnie wybierz wszystkie książki, które mają użytkownicy w tabeli tymczasowej, które nie pasują do książek z docelowego identyfikatora użytkownika i uporządkuj je według rangi. Zwróć uwagę, że ta sama książka może pojawić się na różnych listach użytkowników, dlatego sumujemy rankingi dla każdej książki, dzięki czemu zwykłe książki otrzymują wyższą pozycję.
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)
Książka Z pojawiła się na dwóch listach użytkowników, a więc znalazła się powyżej X,Y,Q,W, która pojawiła się tylko na liście jednego użytkownika. Książka D wypadła najlepiej, ponieważ pojawiła się na liście user_id 2, która miała 3 elementy wspólne z docelowym user_id 1.