I have the following tables:
MOVIE_ID TITLE ---------- ----------------------------- 1 The Shawshank Redemption 2 The Godfather 3 The Godfather: Part II 4 The Dark Knight 5 Pulp Fiction 6 The Good, the Bad and the Ugly 7 Schindler's List 8 Angry Men 9 Fight Club 10 Inception 11 Forrest Gump
DIRECTOR_ID NAME ----------- ------------------------- 1 Tim Robbins 2 Morgan Freeman 3 Marlon Brando 4 Al Pachino 5 Robert De Niro 6 Christian Bale 7 Heath Ledger 8 John Travola 9 Uma Thurman 10 Clint Eastwood 11 Eli Wallach
MOVIE_ID DIRECTOR_ID ---------- ----------- 1 1 1 2 2 3 2 4 3 4 3 5 4 6 4 7 5 8 5 9 6 10
I'd like a query that returns all movies that have directors x, y and z as their director:
Example:
If I look for a movie with and , it should return because I don't have a movie that has both of them as it's director. 和一起看电影,它应该也不会返回,因为我没有一部以导演和导演兼任的电影。
However if I were to look for a movie with and , it should return 和一起看电影,它应该返回
Please suggest alternative if it cannot be done using the above design.
I've attempted it but my query will return results :(
SELECT m.title FROM Movie m
WHERE m.movie_id IN (
SELECT d.movie_id FROM Direct d
WHERE d.director_id IN (
SELECT director_id FROM Director dir
WHERE name IN('Clint Eastwood', 'Al Pachino')));
This is one way to achieve this, viz to group, filter and then count the directors:
SELECT m.title
FROM Movie m
INNER JOIN Direct md
on md.movie_id = m.movie_id
INNER JOIN Directors d
on md.director_id = d.director_id
WHERE
d.name IN('Clint Eastwood', 'Al Pachino')
GROUP BY m.title
HAVING COUNT(DISTINCT d.director_id) = 2;
{Out of interest, aren't these the actors in the movies?}
With the IN operator, your query returns movies that have any of these directors.
You have to check for each director separately:
SELECT *
FROM Movie
WHERE movie_id IN (SELECT movie_id
FROM Direct
WHERE director_id = (SELECT director_id
FROM Directors
WHERE name = 'Clint Eastwood'))
AND movie_id IN (SELECT movie_id
FROM Direct
WHERE director_id = (SELECT director_id
FROM Directors
WHERE name = 'Al Pachino'))
Alternatively, use a compound query to construct a list of movie IDs for both directors:
SELECT *
FROM Movie
WHERE movie_id IN (SELECT movie_id
FROM Direct
WHERE director_id = (SELECT director_id
FROM Directors
WHERE name = 'Clint Eastwood')
INTERSECT
SELECT movie_id
FROM Direct
WHERE director_id = (SELECT director_id
FROM Directors
WHERE name = 'Al Pachino'))
Alternatively, get all records for these two directors from the Direct
table, and then group by the movie to be able to count the directors per movie; we need to have two left:
SELECT *
FROM Movie
WHERE movie_id IN (SELECT movie_id
FROM Direct
WHERE director_id IN (SELECT director_id
FROM Directors
WHERE name IN ('Clint Eastwood',
'Al Pachino')
GROUP BY movie_id
HAVING COUNT(*) = 2)
The shortest one
;with cte as (
select m.title, ROW_NUMBER() over (partition by m.title order by dir.name) rn
from Movie m
inner join Direct d on m.movie_id = d.movie_id
inner join Director dir on dir.DIRECTOR_ID = d.director_id
where dir.name IN ('Clint Eastwood', 'Al Pachino')
)
select * from cte where rn > 1
You can try it as well with SQLite:
SELECT title
FROM movie NATURAL JOIN direct NATURAL JOIN directors
GROUP BY title
HAVING GROUP_CONCAT(name) LIKE '%Morgan Freeman%' AND GROUP_CONCAT(name) LIKE '%Tim Robbins%'
;
Test here
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.