CS50 pset7 movies Q13 - sql

For the pset7 Q13 problem, my SQL code is returning back the error:
Result: ambiguous column name: id
At line 1:
This shouldnt be the case because there is a column name that is "id."
Q13:
In 13.sql, write a SQL query to list the names of all people who starred in a movie in which Kevin Bacon also starred.
Your query should output a table with a single column for the name of each person.
There may be multiple people named Kevin Bacon in the database. Be sure to only select the Kevin Bacon born in 1958.
Kevin Bacon himself should not be included in the resulting list.
SELECT name FROM people, stars WHERE people.id = stars.person_id AND stars.movie_id IN (SELECT id FROM movies, stars, people WHERE movies.id = stars.movie_id AND stars.person_id = people.id AND name = "Kevin Bacon" AND birth = 1958);
UPDATED:
SELECT name FROM people, stars WHERE people.id = stars.person_id AND stars.movie_id IN (SELECT movies.id FROM movies, stars, people WHERE movies.id = stars.movie_id AND stars.person_id = people.id AND name = "Kevin Bacon" AND birth = 1958) AND name != "Kevin Bacon";

Related

SQL Query, list from BOTH values?

Pretty sure this can be answered quite quickly but I just can't seem to find a solution online. Might I add also (if you haven't already figured out) that I'm a complete beginner.
The following query lists all movies starring Johnny Depp and all movies starring Helena Bonham Carter. How do I list all movies starring BOTH Johnny and Helena?
Thank you!
SELECT title FROM movies
JOIN stars
ON stars.movie_id = movies.id
JOIN people
ON people.id = stars.person_id
WHERE people.name IN ("Johnny Depp", "Helena Bonham Carter")
ORDER BY title;
See if this works for you, aggregate the title and filter where there are only 2 - assuming a person can only star in a movie once.
select m.title
from movies m
join stars s on s.movie_id = m.id
join people p on p.id = s.person_id
where p.name in ('Johnny Depp', 'Helena Bonham Carter')
group by m.title
having Count(*) = 2
order by m.title;
Also note that using aliases improves the readability and string literals should be in 'single' quotes, double quotes are reserved for delimiters in most databases.
Here is an alternative. Use IN or EXISTS:
select title
from movies
where id in (select movie_id from stars where person_id =
(select id from people where name = 'Johnny Depp')
)
and id in (select movie_id from stars where person_id =
(select id from people where name = 'Helena Bonham Carter')
)
order by title;
This is very quick for the DBMS to do - even with thousands of actors in your database. I suppose the DBMS would get each actor with an index, get their movies with another index and then get the movie title(s) with yet another index. This is extemely fast.

How to SELECT from column WHERE we have multiple conditions in from another TABLE?

I have 3 TABLES:
movies which has title and id columns
stars which has person_id and movie_id columns
people which has id and name columns
I want to write a SQL query to list the titles of all movies in which both Johnny Depp and Helena Bonham Carter starred.
When I write my query I do not get the title which both Johnny Depp and Helena Bonham Carter starred
SELECT title
FROM movies
WHERE id IN ( SELECT movie_id
FROM people
JOIN stars
ON stars.person_id = people.id
WHERE name = "Helena Bonham Carter"
OR name = "Johnny Depp"
)
GROUP BY title;
You can try the below -
SELECT title
FROM movies
WHERE id IN ( SELECT movie_id
FROM people
JOIN stars
ON stars.person_id = people.id
WHERE name in('Helena Bonham Carter' ,'Johnny Depp')
group by movie_id
having count(distinct name)=2
)
GROUP BY title
In your comment you are saying that you want to see titles where both actors are present (used AND), but query says "OR" - one or second one.. SO maybe just logical operand issue?
Query looks good, but haven`t tested :)
You could also formulate your question as "show me the movie rows where a related row for 'Johnny Depp' and 'Helena Bonham Carter' exists". This can be translated to SQL almost literally.
SELECT title
FROM movies
WHERE EXISTS ( SELECT 'x'
FROM stars
JOIN people ON people.id = stars.person_id
WHERE stars.movie_id = movies.id
AND people.name = 'Helena Bonham Carter' )
AND EXISTS ( SELECT 'x'
FROM stars
JOIN people ON people.id = stars.person_id
WHERE stars.movie_id = movies.id
AND people.name = 'Johnny Depp' );

counting individual elements that meet a certain criteria without duplicates in sqlite3

I'm trying to count all the individual actors from movies in 2004 the problem is when I tried using the count() function it returned how much times every actor appeared in a movie that year.
basically I cant get count() to play well with the GROUP BY function.
SELECT COUNT(name) FROM people
INNER JOIN stars ON stars.person_id = people.id
INNER JOIN movies ON stars.movie_id = movies.id
WHERE movies.year = 2004
GROUP BY name;
relevant tables: movies (id, title, year), stars (movie_id, person_id), people (id, name)
You just need to count the number of DISTINCT person_id in stars (no need to use the people table at all) that have been in movies made in 2004:
SELECT COUNT(DISTINCT person_id) AS num_actors
FROM stars
JOIN movies ON movies.id = stars.movie_id
WHERE movies.year = 2004
Apparently you are not specifying the field you intent to be used for aggregation.Query will return name of actors and respective count of movies. Try below,
SELECT name,COUNT(*) FROM people
INNER JOIN stars ON stars.person_id = people.id
INNER JOIN movies ON stars.movie_id = movies.id
WHERE movies.year = 2004
GROUP BY name;

Find all actors who played in the same movie as Tom Hanks

I have the start of an sql statement where I am supposed to find all actors who have played in the same movie as Tom Hanks.
select a.name, m.title
from actor a
inner join character c
inner join movie m
on a.id = c.actor_id
on c.movie_id = m.id
where a.name = 'Tom Hanks'
However this code only gives me all the names of movies Tom Hanks has played in, but not each actor.
The tables look like this
Actor:
ID
name
Primary Key: ID
Character:
Actor_ID
Movie_ID
Character
Primary Key: (actor_id, movie_id, character)
Foreign Key: actor_id references actor(id)
Foreign Key: movie_id references movie(id)
Movie:
ID
Title
Year
Mpaa_rating
Audience_score
Critics_score
Primary Key: ID
I've been messing around for a while with different sub queries and inner joins but cannot seem to figure out what I'm doing wrong.
Broken out into subqueries for simplicity
-- get all actors that are in movies that tom hanks is in
SELECT *
FROM actor
WHERE
actor_id IN
( -- get all actor ids that are in movies that tom hanks is in
SELECT actor_id
FROM character
WHERE
movie_id IN
( -- get all movies that tom hanks is in
SELECT movie_id
FROM character
WHERE
actor_id IN
( -- get actor ids that equal tom hanks
SELECT id
FROM actor
WHERE name = 'Tom Hanks'
)
)
)
I made an error before, needed an "in" not an "="
You should try this one too:
Select a.name, m.title
From actor a, movie m, character c
Where a.id = c.actor_id
And m.id = c.movie_id
And m.id in ( select movie_id from character where actor_id = (select id from actor where name = 'the name'))

retrieve data from movie database

I'm not a db expert and this is for sure a newbie question.
I've a SQLite db containing data about movies.
The main table (movies) contains:
movie_id (autoincrement, primary);
title;
year;
other fields;
Then I have the actors table:
actor_id (autoincrement);
name;
surname;
Then I have the cast table:
movie_id (related to movies table);
actor_id (related to the actors table, eg. Robin Williams);
character_name (the name of the character, eg. "Mrs Doubtfire");
In a single query I should retrieve all the characters of a given movie (at the application level I've the id of the current movie to start), name and surname of the actor and a list of the movies (!= this current movie) where the actor had a role:
Character_name | Actor | Other movies where we've seen this actor
Mrs Doubtfire | Robin Williams | Mork & Mindy, Dead Poets Society, ...
Other name | Other actor | Related movies,...
Is this possible? How?
Try:
select max(c.character_name) character_name,
max(a.name) || ' ' || max(a.surname) actor,
group_concat(distinct m.title) other_movies
from cast c
join actors a on c.actor_id = a.actor_id
left join cast omc on c.actor_id = omc.actor_id and c.movie_id <> omc.movie_id
left join movies m on omc.movie_id = m.movie_id
where c.movie_id = ?
group by a.actor_id