having trouble with sql about movie theme - mysql

Movie(mID int, title text, year int, director text);
Reviewer(rID int, name text);
Rating(rID int, mID int, stars int, ratingDate date);
For each director, return the director's name together with the title(s) of the movie(s) they directed that received the highest rating among all of their movies, and the value of that rating. Ignore movies whose director is NULL.
I am stuck at highest rating part.
select title, director
from Movie natural join Rating
where director is not NULL
i know i just couldn't really write it.

select distinct director, title, stars
from (movie join rating using (mid)) m
where stars in (select max(stars)
from rating join movie using (mid)
where m.director = director);

Here's one option using a subquery with the max aggregate:
select m.title, m.director, r.stars
from movie m
join rating r on m.mid = r.mid
join (select director, max(stars) maxstars
from rating join movie on rating.mid = movie.mid
group by director) maxr on m.director = maxr.director
and r.stars = maxr.maxstars
where m.director is not null
SQL Fiddle Demo
Edited when I realized you need to group by director instead of movie to get the max(stars) per director.

Related

List the films in which 'Harrison Ford' has appeared

Why is the answer to this question incorrect?
Database
movie (id(PK), title, yr, director(FK), budget, gross)
actor (id(PK), name )
casting (movieid(PK, FK), actorid(PK, FK), ord)
Question: List the films in which 'Harrison Ford' has appeared (original link here)
My answer:
select title
from movie
were id IN
(
select movieid as id
from casting
where actorid IN
(
select id as actorid
from actor
where name = 'Harrison Ford'
)
) X
After correcting were -> where and removing the trailing X the syntax and result where correct.
select title
from movie
where id IN
(
select movieid as id
from casting
where actorid IN
(
select id as actorid
from actor
where name = 'Harrison Ford'
)
)
Error message indicated it was using MariaDB
select title from movie inner join casting on (movie.id = casting.movieid)
inner join actor on (casting.actorid = actor.id)
where actor.name = 'Harrison Ford'
Please use the above SQL code for this question on SQL Zoo; it is in the exercise related to "More Joins". Hence you should be using Joins to solve it
My solution using CTE and JOIN:
-- find the movieid in which Harrison Ford played
WITH t AS (
SELECT DISTINCT movieid
FROM actor
JOIN casting ON actor.id = casting.actorid
WHERE name = 'Harrison Ford'
)
-- Get the movie title using a simple inner join
SELECT title
FROM movie
JOIN t ON movie.id = t.movieid

mysql implicit join+ subquery

I'm meant to use an implicit join to get all the movies with angelina jolie as director or were she stars here's what I have so far
SELECT DISTINCT title, relYear
FROM actor,movie
WHERE director ='Angelina Jolie' OR aID in (SELECT aID
FROM actor
WHERE fName='Angelina' and surname='Jolie'
Here are the relevant tables
movie(id, title, relYear, category, runTime, director,
studioName, description, rating)
actor(aID, fName, surname, gender)
stars(movieID, actorID)
movGenre(movieID, genre)
This returns all of the movies , I think that's because of aID in (SELECT aID
I don't know how to do this without using explicit join on three tables is the subquery even the most efficient approach ? Thanks
This is what I would do on MSSQL. Think it should work on MySql.
Select title, relYear FROM movie WHERE director = 'Angelina Jolie' OR id IN
(SELECT movieId FROM stars inner join actor ON stars.actorId = actor.aID WHERE
actor.fName = 'Angelina' AND surname = 'Jolie')

How do I find the directors for the movies directly?

So I have three separate tables labeled directors, studios, and movie.
Directors columns: id, name, dob, nationality, gender.
Studios columns: id, name, founding date, and director_id
(Foreign Key is director_id)
Movies: ID, name, length, studio_id (foreign key is studios_id)
I have to find all the directors who directed movies with the name awakening but I have no idea how to use foreign keys properly. Best I've come up with was
SELECT name, studio_id FROM studios WHERE name = "awakening"
I have no idea what I'm doing. Please help.
Please try to use INNER JOIN on your query
SELECT d.id, d.name FROM director d INNER JOIN studios s ON d.id = s.director_id INNER JOIN movie m ON s.id = m.studio_id WHERE m.name = "awakening";
SELECT Movies.name as movie_name, Directors.name as director_name
FROM Movies
JOIN Studios ON (Movies.studio_id = Studios.id)
JOIN Directors ON (Studios.director_id = Directors.id)
WHERE Movies.name = 'awakening';

How can I make a query retrieving highest rated movie?

I have the following tables:
Movie ( mID, title, year, director )
Reviewer ( rID, name )
Rating ( rID, mID, stars, ratingDate )
What i want to do is get the directors name along with the movies name which he has directed and got the highest rating.
For example, if Steven Spielberg has directed two movies (namely A and B) which have got 3 stars and 5 stars rating respectively, then the query must show Steven Spielberg and B (movie with the highest rating).
PS: I only need help with the approach. Hope I made myself clear. Please ask if any more info or explanation needed.
Why dont you try this,
SELECT TITLE,DIRECTOR FROM MOVIE,
(SELECT MAX(STARS),mID FROM RATING GROUP BY mID) R
WHERE MOVIE.mID=R.mID
Set up a subselect to get the director and the highest rating:-
SELECT director, MAX(stars)
FROM Movie
INNER JOIN Rating
ON Movie.mID = Rating.mID
INNER JOIN
(
SELECT director, MAX(stars) AS MaxRating
FROM Movie
INNER JOIN Rating
ON Movie.mID = Rating.mID
GROUP BY director
) Sub1
ON Movie.directort = Sub1.director
AND Rating.stars = Sub1.MaxRating
However I presume you will need more details. You do not appear to use the reviewer table at the moment, and I presume that one movie could have had several different reviewers who could have given different ratings. If so you would want to use the above as a subselect to join back against the rating table (macthign on the title and stars), and from that to the reviewer table.
Here you go
SELECT q.* FROM (SELECT m.*,MAX(r.`stars`) AS maxrating FROM `movie` m
INNER JOIN `rating` r ON (m.`mID` = r.`mID` )
GROUP BY r.`mID` ORDER BY maxrating DESC ) q GROUP BY q.director
ORDER BY q.maxrating DESC
And i am sure this question is taken from the quiz of DB class provided by stanford university
Here is your fiddle
Another way to do that is:
select m.title, max(r.stars) as stars
from rating r
inner join movie m on r.mid = m.mid
group by r.mid
order by m.title
this code should suffice :
select distinct m1.director, m1.title, r1.stars from movie m1
join rating r1 on m1.mID = r1.mID
left join (
select m2.director, r2.stars from movie m2
join rating r2 on m2.mID = r2.mID
) s on m1.director = s.director and r1.stars < s.stars
where s.stars is null and m1.director is not null;

MYSQL, Max,Group by and Max

I am having the following two table.
1.Movie Detail (Movie-ID,Movie_Name,Rating,Votes,Year)
2.Movie Genre (Movie-ID,Genre)
I am using the following query to perform join and get the movie with highest rating in each
genre.
select Movie_Name,
max(Rating) as Rating,
Genre from movie_test
inner join movie_genre
where movie_test.Movie_ID = movie_genre.Movie_ID
group by Genre
In the output Rating and Genre are correct but the Movie_Name is incorrect.
can anyone suggest what changes I should make to get the correct movie name along with rating and genre.
SELECT g.*, d.*
FROM MovieGenre g
INNER JOIN MovieDetail d
ON g.MovieID = d.MovieID
INNER JOIN
(
SELECT a.Genre, MAX(b.Rating) maxRating
FROM MovieGenre a
INNER JOIN MovieDetail b
ON a.MovieID = b.MovieID
GROUP BY a.Genre
) sub ON g.Genre = sub.Genre AND
d.rating = sub.maxRating
There is something wrong with your schema design. If a Movie can have many Genre as well as Genre can be contain on many Movie, it should be a three table design.
MovieDetails Table
MovieID (PK)
MovieName
MovieRating
Genre Table
GenreID (PK)
GenreName
Movie_Genre Table
MovieID (FK) -- compound primary key with GenreID
GenreID (FK)
This is a common MySQL problem - specifying non-aggregate/non-aggregated-by columns in an aggregate query. Other flavours of SQL do not let you do this and will warn you.
When you do a query like yours, you are selecting non-aggregate columns in an aggregated group. Since many rows share the same genre, when you select Movie_Name it picks one row at random from each group and displays that one, because there is no general algorithm to guess the row you want and return the values of that.
You might ask 'why does it pick randomly? It could pick the one that max(Rating) belongs to?' but what about other aggregate columns, like avg(Rating)? What row does it pick there? What if two rows have the same max, anyway? Therefore it cannot have an algorithm to pick a row.
To solve a problem like this, you have to restructure your query, something like:
select Movie_Name,
Rating,
Genre from movie_test mt
inner join movie_genre
where movie_test.Movie_ID = movie_genre.Movie_ID
and Rating = (select max(Rating) from movie_test mt2 where mt.Genre = mt2.Genre
group by Genre
limit 1
This will select the row with the rating being the same as the maximum rating for that genre, using a subquery.
Query:
SELECT t.Movie_Name,
t.Rating,
g.Genre
FROM movie_test t
INNER JOIN movie_genre g ON t.Movie_ID = g.Movie_ID
WHERE t.Movie_ID = (SELECT t1.Movie_ID
FROM movie_test t1
INNER JOIN movie_genre g1 ON t1.Movie_ID = g1.Movie_ID
WHERE g1.Genre = g.Genre
ORDER BY t1.Rating DESC
LIMIT 1)