如何通过 SQL 查询来显示另一个用户对其他产品的评级最相同的评级

问题描述 投票:0回答:1

我在编写 SQL 查询方面不是很先进,我正在尝试找出一个查询,该查询将在产品页面上显示与访问该页面的用户对产品品味最相似的用户的评级。我在下面提供了一个场景,希望可以让您轻松理解我想要实现的目标。

MySQL 数据库示例

行_id 用户ID 评分 产品_id
1 1 41 1
2 2 39 1
3 3 26 1
4 4 56 1
5 1 67 2
6 2 66 2
7 3 72 2
8 4 82 2
9 5 64 2
10 2 55 3
11 3 47 3
12 4 70 3

场景
访问该页面的人是 user_id #1,他们正在查看 Product_id #3。

目标
我正在尝试找出最干净、最有效的方法来显示对 user_id #3 给出的评级,该评级来自与 user_id #1 具有最相同评级的用户(基于两个用户都提交了评级的所有其他产品)。

我希望这也能忽略任何未提交至少 1 个 1-50 之间的产品评级和至少 1 个 51-100 之间的产品评级的用户(所以基本上我想排除总是给出高或总是给出低的用户一切的评级)。

如果没有用户根据上述标准提交评分,则只需返回“n/a”即可。

消除过程
user_id #5 的行将被排除,因为该用户尚未对 Product_id #3 进行评级。

user_id #4 的行也将被排除,因为该用户尚未提交 1-50 之间的任何评分。

这使得用户 #2 和用户 #3 留下来,因为他们都满足对 1-50 之间的产品以及 51-100 之间的产品提交评级的标准。

产品 #1 被用户 #1 评为 41,被用户 #2 评为 39(相差 2),被用户 #3 评为 26(相差 15)。

产品 #2 被用户 #1 评分为 67,被用户 #2 评分为 66(相差 1),被用户 #3 评分为 72(相差 5)。

将其计算为平均值,与用户 #1 给出的评分相比,用户 #2 的平均差异为 1.5,而用户 #3 与用户 #1 对相同产品给出的评分的平均差异为 10。

结果
根据示例数据库表,用户 #2 将具有与用户 #1 最相同的评级,并且产品 #3 的预期输出应为:55

任何有关如何完成这项工作的帮助将不胜感激。

sql mysql collaborative-filtering
1个回答
0
投票

我创建了一个小提琴来执行必要的操作:http://sqlfiddle.com/#!9/e1caa2/1

下面是完整的sql查询。 其结构如下:

  • 选择所有评论过产品3的用户
  • 选择所有具有适当评级的用户(至少一个 >50 和一个 <50)
  • 对上述两个结果进行内连接以查找满足这两个条件的用户
  • 将原始表与自身右连接
    product_id
    以获得用户之间的不同评分
  • 在右连接上添加条件,以便将用户 1 的评分与满足条件的用户的评分进行比较
  • 计算右连接中评级之间的绝对差异
  • 绝对差值的平均值
  • 订购平均值
  • 最后限制为 1 个用户(平均绝对差值最小的用户)

SQL查询:

SELECT user_id
FROM
  (SELECT t2.user_id,
          abs(t1.rating-t2.rating) AS difference
   FROM table1 t1
   RIGHT JOIN table1 t2 ON t1.product_id = t2.product_id
   WHERE t1.user_id = '1'
     AND t2.user_id in
       (SELECT user_with_appropriate_rating.user_id
        FROM
          (SELECT user_id
           FROM
             (SELECT user_id,
                     max(rating) AS maxrating,
                     min(rating) AS minrating
              FROM table1
              GROUP BY user_id) user_with_rating
           WHERE user_with_rating.maxrating >50
             AND user_with_rating.minrating<50) user_with_appropriate_rating
        INNER JOIN
          (SELECT DISTINCT user_id
           FROM table1
           WHERE product_id = '3') user_has_reviewed_product ON user_with_appropriate_rating.user_id = user_has_reviewed_product.user_id)) product_difference
GROUP BY user_id
ORDER BY avg(difference)
LIMIT 1

为了完整起见,sql fiddle 中使用的模式:

CREATE TABLE IF NOT EXISTS `table1` (
  `row_id` int(1) NOT NULL,
  `user_id` int(1) NOT NULL,
  `rating` int(1) NOT NULL,
  `product_id` int(1) NOT NULL,
  PRIMARY KEY (`row_id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `table1` (`row_id`, `user_id`, `rating`, `product_id`) VALUES
  ('1', '1', '41', '1'),
  ('2', '2', '39', '1'),
  ('3', '3', '26', '1'),
  ('4', '4', '56', '1'),
  ('5', '1', '67', '2'),
  ('6', '2', '66', '2'),
  ('7', '3', '72', '2'),
  ('8', '4', '82', '2'),
  ('9', '5', '64', '2'),
  ('10', '2', '55', '3'),
  ('11', '3', '47', '3'),
  ('12', '4', '70', '3');
© www.soinside.com 2019 - 2024. All rights reserved.