【问题标题】:How do I remove results based on conditions to calculate an average如何根据条件删除结果以计算平均值
【发布时间】:2021-02-22 01:07:04
【问题描述】:

我有下面的架构。一个简单的解释是:

  1. 鲍勃评分提高了 5/5
  2. 詹姆斯被评为 1/5
  3. 梅西百货评分 5/5

逻辑:

  1. 如果我是 personA,请查找我已阻止的所有人。
  2. 查看所有电影评论。
  3. 任何留下了影评且 personA 已屏蔽的人,将其从计算中移除。
  4. 计算电影的平均评分。

CREATE TABLE movies (
  id integer AUTO_INCREMENT primary key,
  name varchar(100) NOT NULL
);

CREATE TABLE customer (
  id integer AUTO_INCREMENT primary key,
  name varchar(100) NOT NULL
);

CREATE TABLE reviews (
  id integer AUTO_INCREMENT primary key,
  rating integer NOT NULL,
  cus_id integer NOT NULL,
  movie_id integer NOT NULL,
  FOREIGN KEY (cus_id) REFERENCES customer(id),
  FOREIGN KEY (movie_id) REFERENCES movies(id)
);

CREATE TABLE blocked(
  id integer AUTO_INCREMENT primary key,
  cus_id integer NOT NULL, -- This is the person blocking
  blocked_cus_id integer NOT NULL, -- This is the person who is blocked
  FOREIGN KEY (cus_id) REFERENCES customer(id),
  FOREIGN KEY (blocked_cus_id) REFERENCES customer(id)
);

INSERT INTO movies (id, name) VALUES (1, 'up');
INSERT INTO customer (id, name) VALUES (1, 'bob'), (2, 'james'), (3, 'macy');
INSERT INTO reviews (id, rating, cus_id, movie_id) VALUES (1, 5, 1, 1), (2, 1, 2, 1), (3, 5, 3, 1);
INSERT INTO blocked (id, cus_id, blocked_cus_id) VALUES (1, 1, 2);

如果评论在黑名单上,我不明白如何摆脱评论

SELECT m.name, avg(r.rating) as avg_rating
FROM movies m
JOIN reviews r ON m.id = r.movie_id
JOIN blocked b on r.cus_id = b.blocked_cus_id
WHERE b.cus_id = 1 -- Viewing the database as bob

当我以 bob 形式查看数据库时,我应该得到:

+-------+------------+
| movie | avg_rating |
+-------+------------+
| up    |          5 |
+-------+------------+

当我将数据库视为 macy 时,我应该得到:

+-------+------------+
| movie | avg_rating |
+-------+------------+
| up    |       3.67 |
+-------+------------+

【问题讨论】:

  • blocked 表背后的逻辑是什么?是否应该忽略任何被其他人阻止的评论?还是其他一些逻辑?
  • 如果 Bob 阻止了 James。然后当 Bob 找到一部电影的平均分数时。然后,在计算特定电影的平均值时,詹姆斯(对任何电影)提出的任何评论都会被完全忽略。
  • @TimBiegeleisen 更新了它。我只是假设数据库是空的。
  • 另外,如果 Macy 正在查看数据库,那么 macy 并没有阻止任何人,所以所有评论都被考虑到该特定电影 @TimBiegeleisen

标签: mysql sql database join


【解决方案1】:

如果不使用存在子句,我不知道如何表达您的逻辑。我可以在这里试试:

SELECT m.name, AVG(r.rating) AS avg_rating
FROM movies m
INNER JOIN reviews r ON m.id = r.movie_id
WHERE NOT EXISTS (SELECT 1 FROM blocked b
                  WHERE b.blocked_cus_id = r.cus_id AND b.cus_id = 1)
GROUP BY m.name;

注意我们要按电影名称聚合,所以这里需要GROUP BY。 exists 子句表示从平均评分中排除我们可以找到属于某个客户(在本例中为cus_id = 1)的被阻止条目的任何评论。

【讨论】:

  • 很抱歉,如果blocked_cus_id 永远不会为空怎么办。阻止列表仅包含客户已阻止的人员。我更新了创建表 sql
  • 如果客户被阻止,您想打折/忽略评论。我的查询具有应该这样做的逻辑。如果你不能让它继续工作,那么将示例数据添加到你的问题中,或者可能是一个演示链接。
  • 我添加了一些演示数据:sqlfiddle.com/#!9/6563896/6 这是我的架构。问题是它没有正确计算平均值。
  • 是的,它很难,所以,我不知道怎么做。所以如果你检查一下詹姆斯的观点,他没有阻止任何人,所以他的平均得分也应该是 5,因为詹姆斯没有阻止任何人。但他对小丑电影的平均看法是 3.667
  • 我认为我更新的答案现在应该对你有用。请检查。
猜你喜欢
  • 2021-02-26
  • 1970-01-01
  • 2021-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多