-3

Could someone help me with how to approach fixing my SQL? I am handling five tables.
The expected results are,

  1. "write a SQL query to list the titles of all movies in which both Johnny Depp and Helena Bonham Carter starred"
  2. Your query should output a table with a single column for the title of each movie.
  3. You may assume that there is only one person in the database with the name Johnny Depp.
  4. You may assume that there is only one person in the database with the name Helena Bonham Carter.

     CREATE TABLE movies (
                         id INTEGER,
                         title TEXT NOT NULL,
                         year NUMERIC,
                         PRIMARY KEY(id)
                        ); 
    
     CREATE TABLE stars (
                     movie_id INTEGER NOT NULL,
                     person_id INTEGER NOT NULL,
                     FOREIGN KEY(movie_id) REFERENCES movies(id),
                     FOREIGN KEY(person_id) REFERENCES people(id)
                       ); 
    
    CREATE TABLE directors (
                     movie_id INTEGER NOT NULL,
                     person_id INTEGER NOT NULL,
                     FOREIGN KEY(movie_id) REFERENCES movies(id),
                     FOREIGN KEY(person_id) REFERENCES people(id)
                 ); 
    
    CREATE TABLE ratings (
                     movie_id INTEGER NOT NULL,
                     rating REAL NOT NULL,
                     votes INTEGER NOT NULL,
                     FOREIGN KEY(movie_id) REFERENCES movies(id)
                   ); 
    
    CREATE TABLE people (
                     id INTEGER,
                     name TEXT NOT NULL,
                     birth NUMERIC,
                     PRIMARY KEY(id)
                 );
    

This results in 59 rows, where it is supposed to be only 6 rows.

 SELECT title FROM movies  WHERE id IN (SELECT DISTINCT movie_id FROM
 stars WHERE person_id =  (SELECT id FROM people  WHERE name IN
 ("Johnny Depp", "Helena Bonham Carter")));

I see other posts talking about using "WHERE IN" would be helpful, and I am indeed using it.

Eric Brandt
  • 7,886
  • 3
  • 18
  • 35
FluffyCat
  • 55
  • 2
  • 9
  • 2
    The result set that you're getting is a list of movies that star _either_ Johnny Depp or HBC. `JOIN` the tables, `movies` to `stars` to `people`, which is vastly more efficient than nested `WHERE` clauses, then have a look at `WHERE EXISTS` rather than `WHERE IN`, since you have two conditions you have to meet. – Eric Brandt May 01 '20 at 03:45
  • @EricBrandt Thanks for your reply. With the help of you and more google search, I came up with using the `HAVING` clause in SQL. (I have not yet come up with the solution yet though.) The reason why I used `WHERE IN` is because there is NO table cell that has two values such as 'JD' AND 'HBC'. So, I thought the right way would be to select a table cell that includes either 'JD' or 'JBC', then count the total number of movies. However, my mistake was not making sure those movies had BOTH JD and JBC starred. Does that make sense to you? – FluffyCat May 01 '20 at 06:26

6 Answers6

4

I first used a few join statements to get a table where I have all the movie titles where these two actors were starred in.

I cleaned up the data by grouping by movie title, which groups similar movie titles.

I then used the COUNT function to see where the movie title was mentioned twice, which would mean both actors were involved.

-- inspired by https://stackoverflow.com/a/477035

SELECT movies.title FROM stars
JOIN movies ON stars.movie_id = movies.id
JOIN people ON stars.person_id = people.id
WHERE people.name IN ('Johnny Depp', 'Helena Bonham Carter')
GROUP BY movies.title
HAVING COUNT(movies.title) = 2;
H Ali
  • 41
  • 3
  • Welcome to StackOverflow. While this code may solve the question, [including an explanation](https://meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit](https://stackoverflow.com/posts/65718145/edit) your answer to add explanations and give an indication of what limitations and assumptions apply. – Ruli Jan 14 '21 at 12:29
2

I used like below and it was a little bit faster than using INTERSECT.

SELECT title FROM movies WHERE id IN (
SELECT movie_id FROM stars
JOIN people
ON stars.person_id = people.id
WHERE name = "Helena Bonham Carter" AND movie_id IN
(SELECT movie_id FROM stars WHERE person_id IN 
(SELECT id FROM people WHERE name = "Johnny Depp")
))
ORDER BY title
Noah
  • 81
  • 1
  • 7
1

Using JOIN and INTERSECT helped me solve this one.

Something like this:

Select title from movies 
join stars on stars.movie_id = movies.id 
join people on people.id = stars.person_id 
where people.name = "Helena Bonham Carter" 
INTERSECT 
Select title from movies 
join stars on stars.movie_id = movies.id 
join people on people.id = stars.person_id 
where people.name = "Johnny Depp";
kj9849
  • 21
  • 3
1

Using count:

SELECT title FROM movies WHERE id IN 
(SELECT movie_id FROM 
(SELECT count(person_id) as together, movie_id FROM stars WHERE person_id IN
(SELECT id FROM people WHERE name IN ('Johnny Depp','Helena Bonham Carter')) 
GROUP BY movie_id) 
WHERE together > 1);
Mod
  • 65
  • 6
1

I have tested all recommendation here, and I believed this is the fastest one until now, although it seems little cryptic :

Time: 0.48

SELECT title FROM movies WHERE id IN 
(
    SELECT movie_id FROM stars WHERE person_id =
        (SELECT id FROM people WHERE name = "Helena Bonham Carter") 
    and
        movie_id IN
            (
                 SELECT movie_id FROM stars WHERE person_id =
                     (SELECT id FROM people WHERE name = "Johnny Depp")
            )
)
Mahmoud
  • 53
  • 8
1

In this case, I did not use JOIN option, and more as the traditional style in order to get it better in my mind. I ll still try another way. But this option worked fine.

SELECT movies.title FROM movies
WHERE id IN (SELECT movie_id FROM stars WHERE person_id IN
(SELECT id FROM people WHERE name = "Johnny Depp"))
AND id IN (SELECT movie_id FROM stars WHERE person_id IN
(SELECT id FROM people WHERE name = "Helena Bonham Carter"));
Avispa10
  • 11
  • 3