mysql - 用于过滤的 SQL

标签 mysql

通过引用Collaborative filtering in MySQL? ,我创建了以下几个:

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 |
+---------+------------+



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

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

我想做的是,假设用户 1 和 2 有相似的行为(之前选择了 A、B、C 且评级匹配),因此我会向用户 A 推荐 D,因为它的评级更高。

上面的代码似乎没有这样做?因为,排名第一的是X。我如何更改代码才能达到提到的目标?

或者,实际上现有的方法对于推荐来说是否更好/更准确?

最佳答案

现有的查询是根据每本书的排名总值对结果进行排名,然后使用比率作为具有相同总排名的书籍的平局。 (此外,速率本质上是随机的,因为相似的速率不会聚合、分组或在功能上依赖于查询中的分组项。)

因此,X 的排名将高于 D,因为它已被一名排名 3 的用户和一名排名 1 的用户选择,总排名为 4,而 D 仅被一名排名 3 的用户选择.

您可以更改查询以包含按排名加权的评级元素 - 例如:

select similar.book_id, 
       sum(ub_rank.rank) total_rank, 
       sum(ub_rank.rank*similar.rate) wtd_rate
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 wtd_rate desc, total_rank desc

- 尽管在这种情况下,它的排名仍会高 X,因为与 D 相比,它的排名为 3 的用户评分为 7,加上排名 1 的用户评分为 10,总排名为 31总排名24。

( SQLFiddle here )

如果您希望 X 的排名高于 D,您需要决定使用什么标准来使 X 的排名高于 D。

关于mysql - 用于过滤的 SQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15636325/

相关文章:

mysql - 如何设置两个MySQL数据字段,使其中一个可以为空,但不能同时为空?

php - datetime-local 值未出现在输入标签上

mysql - 使 MySQL 可以远程访问,安装在 Windows PC 上

php - 如何根据另一个表获取每个值的计数?

php - 如何从 Laravel 查询中获得相反的结果

mysql - Visual Studio Community 2015 MySQL 数据源未出现

java.io.IOException :Cannot run program "mysql":CreateProcess error=2, 系统找不到指定的文件

php - MySql 添加新记录时触发错误

c# - 使用 C# 添加 entityFramework 部分

php - 带有 ACL 的 MySQL DB 的 Rest 接口(interface)