How do I remove results based on conditions to calculate an average

烂漫一生 提交于 2021-02-09 11:44:11

问题


I have the schema below. A quick explanation of it is:

  1. bob rated up 5/5
  2. james rated up 1/5
  3. macy rated up 5/5

The logic:

  1. If I am personA, look up everyone I have blocked.
  2. Look up all the movie reviews.
  3. Anyone who has left a movie review, and personA has blocked, remove them from the calculation.
  4. Calculate the average rating of the movies.

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);

I don't understand how I can get rid of reviews if its on a block list

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

When I view the database as bob, I should get:

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

When I view the database as macy, I should get:

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

回答1:


I don't know how to express your logic without using an exists clause. I might try here:

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;

Note that we want to aggregate by movie name, so we need GROUP BY here. The exists clause says to exclude from the average rating any review for which we can find a blocked entry belonging to a certain customer (in this case, cus_id = 1).



来源:https://stackoverflow.com/questions/64763062/how-do-i-remove-results-based-on-conditions-to-calculate-an-average

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!