Créez un tableau et insérez les données de test :
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');
Joignez les données de test sur elles-mêmes par book_id et créez une table temporaire pour contenir chaque user_id et le nombre de livres qu'il a en commun avec le user_id cible :
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)
Nous pouvons voir que user_id a 3 en commun avec user_id 1, mais user_id 3 et user_id 4 n'en ont qu'un chacun.
Ensuite, sélectionnez tous les livres que les utilisateurs de la table temporaire possèdent et qui ne correspondent pas aux livres de l'utilisateur cible, et organisez-les par rang. Notez que le même livre peut apparaître dans différentes listes d'utilisateurs, nous additionnons donc les classements pour chaque livre afin que les livres communs obtiennent un classement plus élevé.
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)
Le livre Z est apparu dans deux listes d'utilisateurs et a donc été classé au-dessus de X, Y, Q, W qui n'apparaissait que dans la liste d'un utilisateur. Le livre D a obtenu les meilleurs résultats car il figurait dans la liste de l'user_id 2, qui avait 3 éléments en commun avec l'user_id cible 1.