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

不想你离开。 提交于 2021-02-10 16:20:51

问题


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

  1. bob rated the movie up, 5/5
  2. james rated the movie up, 1/5
  3. macy rated the movie up, 5/5
  4. No one has rated the movie avengers.

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'), (2, 'avengers');
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 received some help with this question here: How do I remove results based on conditions to calculate an average (and the statement was correct) but when I want to find the rating for a specific movie the statement it only shows the movie if it had a rating. I want it to show the movie regardless if it has a rating or not. If it doesn't have a rating it should just say 0. Below, the movie avengers has no ratings and no results are shown.

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)
AND m.id = 2
GROUP BY m.name;

The above select statement should show:

+----------+------------+
| movie    | avg_rating |
+----------+------------+
| avengers |          0 |
+----------+------------+

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:


Do you want a left join? Starting from your current query, that would be:

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


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

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