-1

I have following tables for an SQL test; See SQLFiddle here

> SELECT * FROM `Movie`;
+-----+-------------------------+------+------------------+
| mID | title                   | year | director         |
+-----+-------------------------+------+------------------+
| 101 | Gone with the Wind      | 1939 | Victor Fleming   |
| 102 | Star Wars               | 1977 | George Lucas     |
| 103 | The Sound of Music      | 1965 | Robert Wise      |
| 104 | E.T.                    | 1982 | Steven Spielberg |
| 105 | Titanic                 | 1997 | James Cameron    |
| 106 | Snow White              | 1937 | <null>           |
| 107 | Avatar                  | 2009 | James Cameron    |
| 108 | Raiders of the Lost Ark | 1981 | Steven Spielberg |
+-----+-------------------------+------+------------------+
> SELECT * FROM Rating;
+-----+-----+-------+------------+
| rID | mID | stars | ratingDate |
+-----+-----+-------+------------+
| 201 | 101 | 2     | 2012-01-22 |
| 201 | 101 | 4     | 2013-01-27 |
| 202 | 106 | 4     | <null>     |
| 203 | 103 | 2     | 2008-01-20 |
| 203 | 108 | 4     | 2002-01-12 |
| 203 | 108 | 2     | 2009-01-30 |
| 204 | 101 | 3     | 2010-01-09 |
| 205 | 103 | 3     | 2010-01-27 |
| 205 | 104 | 2     | 2010-01-22 |
| 205 | 108 | 4     | <null>     |
| 206 | 107 | 3     | 2013-01-15 |
| 206 | 106 | 5     | 2014-01-19 |
| 207 | 107 | 5     | 2000-01-20 |
| 208 | 104 | 3     | 1999-01-02 |
+-----+-----+-------+------------+
> SELECT * FROM Reviewer;
+-----+------------------+
| rID | name             |
+-----+------------------+
| 201 | Sarah Martinez   |
| 202 | Daniel Lewis     |
| 203 | Brittany Harris  |
| 204 | Mike Anderson    |
| 205 | Chris Jackson    |
| 206 | Elizabeth Thomas |
| 207 | James Cameron    |
| 208 | Ashley White     |
+-----+------------------+

I have solved all questions, except these two:

1.) For each movie that has at least one rating, find the movie title and total number of stars, the highest star and the person who gave highest star.

What I got:

SELECT m.title, ra.stars, re.name
FROM Movie m
JOIN(
    SELECT R.*
    FROM Rating R
    JOIN(
        SELECT mid, MAX(stars) AS Stars
        FROM Rating
        GROUP BY mid
    ) D ON R.mid = D.mid AND R.Stars = D.Stars
) Ra ON m.mid = ra.mid
JOIN Reviewer re ON ra.rid = re.rid;
+-------------------------+-------+------------------+
| title                   | stars | name             |
+-------------------------+-------+------------------+
| Gone with the Wind      | 4     | Sarah Martinez   |
| Raiders of the Lost Ark | 4     | Brittany Harris  |
| The Sound of Music      | 3     | Chris Jackson    |
| Raiders of the Lost Ark | 4     | Chris Jackson    |
| Snow White              | 5     | Elizabeth Thomas |
| Avatar                  | 5     | James Cameron    |
| E.T.                    | 3     | Ashley White     |
+-------------------------+-------+------------------+

What is missing: I cannot find a way to add SUM(stars) per movie to the table.

2.) For all cases where the same reviewer rated the same movie twice and gave it a higher rating the second time, return the reviewer's name and the title of the movie.

What I got so far:

SELECT title, name
FROM Movie m
JOIN Rating ra ON m.mid = ra.mid
JOIN Reviewer re ON ra.rid = re.rid
GROUP BY title, name
HAVING COUNT(*) > 1;
+-------------------------+-----------------+
| title                   | name            |
+-------------------------+-----------------+
| Gone with the Wind      | Sarah Martinez  |
| Raiders of the Lost Ark | Brittany Harris |
+-------------------------+-----------------+

What is missing: I have all movies that were rated twice by the same reviewer, however I do not know how to filter for cases were the latest review has more stars than the earlier.

I would highly appreciate if anyone could point me in the right direction here. Stack overflow has been extremely helpful today for me :)

EDIT: Add my attempts and what is missing.

RJ7
  • 883
  • 9
  • 17
neurotronix
  • 221
  • 1
  • 2
  • 11
  • 2
    you cannot get your answer by flattering. show us what you have tried so far – jose_bacoy Apr 19 '18 at 19:06
  • Without giving you the answer (show us something you have tried) you should break down the questions you are trying to solve. For example, 1) Each movie that has at least one rating, this would be an inner join on `Movies.mID = Ratings.mID`. You can then join to Reviewer on `Movies.rID = Reviewer.rID`. It sounds like you might be new with SQL, I would reconmend looking at various joins and when to use them. Also take a look at functions such as `max` and `count`. – RJ7 Apr 19 '18 at 19:17
  • You guys are right, @âńōŋŷXmoůŜ. I edited my question to add what I have got so far. – neurotronix Apr 19 '18 at 19:24
  • Thank you for the hints @RJ7. I am quite new to SQL, you are right. But I have quite some experience with python/pandas, so I understand all the things like `MIN, MAX, COUNT` or `GROUP BY`. – neurotronix Apr 19 '18 at 19:27
  • 1
    Thank you for the downvotes everyone. Message received. – neurotronix Apr 19 '18 at 19:31

1 Answers1

0

This should give you what you want for number 1, for number 2 I would need the data in a sqlfiddle to play around with. In the meantime, I would suggest looking at lag although some combination of first and last might give you what you want. *Note this will not give you the EXACT answer, it is meant to be a reference.

select mov.title, sum(rat.stars), max(rat.stars), rev.name
from Movie mov,
  Rating rat,
  Reviewer rev
where mov.mid = rat.mid
and rat.rid = rev.rid
group by mov.title;
RJ7
  • 883
  • 9
  • 17
  • Nope, your solution does not work. I tried to add `SUM(stars)` also in the innermost join, but it doesnt work: `Unknown column 'ra.count_stars' in 'field list'` – neurotronix Apr 19 '18 at 19:34
  • As I don't have the data in a table, what was the output of running this? Add the DDL to a sqlfiddle for us to see. Thanks. – RJ7 Apr 19 '18 at 19:36
  • Here is a sqlfiddle with the dataset already built: http://sqlfiddle.com/#!9/10fbc/407 – neurotronix Apr 19 '18 at 19:38
  • Does that sqlfiddle work for you @RJ7? I am not sure as I never used it. – neurotronix Apr 19 '18 at 19:44
  • What?! I totally was not aware that this was possible without joining the tables. Thanks @RJ7 – neurotronix Apr 19 '18 at 19:55
  • This actually does join the tables, since we want INNER joins, the syntax I provided is correct and cleaner IMO on trivial SQL. See https://softwareengineering.stackexchange.com/questions/78225/using-join-keyword-or-not as reference. – RJ7 Apr 19 '18 at 19:57
  • One issue though, on my system I get this error: `(1055, u"Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'foo.rev.name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by")` – neurotronix Apr 19 '18 at 20:01
  • Info on my system: `mycli 1.16.0, running on CPython 2.7.10, mysql 5.7.21 Homebrew` – neurotronix Apr 19 '18 at 20:02
  • Ok, no worries! I am not running SQL through python. mycli is a cli tool for mysql that is built with python as it seems. It is pretty neat, comes with autocompletion and you can edit queries in your $EDITOR of choice. – neurotronix Apr 19 '18 at 20:12
  • Anyways, thanks again for your time @RJ7. My time is running out, so I just hand in what I got so far, and let destiny decide :) – neurotronix Apr 19 '18 at 20:19
  • 1) this query is against the sql standard and will only run in mysql if the only_full_group_by sql mode is not enabled. Luckily this sql mode is now enabled by default in mysql preventing such monsters from running. 2) Do not use the old sql standard for joining tables. This is not cleaner at all, since join and filtering conditions are mixed in the where clause and extending the join clause could be difficult (comma operator having a lower precedence than any other join operator) – Shadow Apr 19 '18 at 23:39
  • Nope, this is not clear, this is confusing. In most rdbms this query would not run no matter how you configure it because it is against the sql standard. – Shadow Apr 20 '18 at 00:10