I have written a query but I get wrong results.
These are the tables:
|actor|-->|role|-->|movie|->|movie_has_genre|-->|genre|
In each table I have (table: fields):
actor: actor_id
role: actor_id, movie_id
movie:movie_id
movie_has_genre: movie_id, genre_id
genre: genre_id
I'm looking to find the actors' ids that have played in all kinds of movies.
My code is:
SELECT a.actor_id
FROM actor a
WHERE NOT EXISTS(
SELECT *
FROM genre g
WHERE NOT EXISTS(
SELECT *
FROM movie m
WHERE m.movie_id in(
SELECT m1.movie_id
FROM movie m1, role r, movie_has_genre mg
WHERE a.actor_id=r.actor_id AND r.movie_id=m1.movie_id
AND m1.movie_id=mg.movie_id AND mg.genre_id=g.genre_id))
);
Can you help?
It's pseudo code but you can get the idea
select a.actor_id, count(mg.genre_id) as countkinds
from actor a
join role r on r.actor_id = a.actor_id
join movie_has_genre mg on mg.movie_id =r.movie_id
group by a.actor_id
having count(mg.genre_id) = (select count(*) from genre)
just join actors to genre_ids, count it and return only all played in all genres.
note you don't need to join movies table since you can join role and movie_has_genre for the same movie directly by the id
Related
I'm trying to find movie_ids for movies that both johnny Depp and Helena Bonham Carted played in. I'm using SQLite3 as software and the famous IMDB dataset.
The result I got: ids for movies that either of them played
The Desired result: ids for movies that both of them played in
select movie_id from stars where person_id in
(select id from people where name in
("Johnny Depp", "Helena Bonham Carter"))
);
SELECT s.movie_id
FROM stars s
INNER JOIN people p ON p.id = s.person_id
WHERE p.name in ('Johnny Depp', 'Helena Bonham Carter')
GROUP BY s.movie_id
HAVING COUNT(DISTINCT p.id) = 2
I am trying to insert into a new table all the names of the movies where helena bonhab carter and johnny depp starred in. I am selecting information firstfrom a table called movies which has a title and an id. and then from a table called stars which has a movie_id and a person_id. and lastly I am selecting from a table called people which has a id and name columns. I think my problem is in the union line but i don't know why.
CREATE TABLE jh( title TEXT)
INSERT INTO jh(title)
SELECT movies.title
FROM movies
WHERE movies.id in ( SELECT stars.movie_id FROM stars WHERE stars.person_id in(SELECT
people.id FROM people WHERE people.name = ' Johnny Depp' UNION SELECT people.id FROM people
WHERE people.name = 'Helena Bonham Carter'))
You can join the tables, filter for the actors you want, group by movie and set the condition the HAVING clause:
SELECT m.title
FROM movies m
INNER JOIN stars s ON s.movie_id = m.id
INNER JOIN people p ON p.id = s.person_id
WHERE p.name IN ('Johnny Depp', 'Helena Bonham Carter')
GROUP BY m.id, m.title
HAVING COUNT(*) = 2 -- the number of the actors
I really suggest you don't do query like that. for example, you could select all names in one single WHERE condition. And be ready to use JOIN if you have several tables need to be connected.
SELECT M.Title
FROM Movies M INNER JOIN Stars S on M.id = S.Movie_Id
INNER JOIN People P on S.PersonID = P.PersonID
WHERE P.Name in ('Johnny Depp','Helena Bonham Carter')
I need to create a new table with the title of the movies starred by Johnny Depp AND Helena Bonham Caster.
I have these tables:
Movies: (ID, title and year)
Stars: (Movie_ID, Person_ID)
People: (ID, Name, and Birth year)
CREATE TABLE johnny_helena (title TEXT);
INSERT INTO johnny_helena (title)
SELECT title
FROM movies
WHERE id IN (SELECT movie_id FROM stars WHERE person_id IN (SELECT id FROM people WHERE name = 'Johnny Depp') AND person_id IN (SELECT id FROM people WHERE name = 'Helena Bonham Caster'))
When I execute this code I receive one Table with 0 rows but should be 6.
I'm new em SQL and I believe that I'm making a foolish mistake. So, how I can fix this error?
Thanks.
One option uses joins and aggregation:
INSERT INTO johnny_helena (title)
SELECT m.title
FROM movies m
INNER JOIN stars s ON s.movie_id = m.id
INNER JOIN people p ON p.id = s.person_id
WHERE p.name in ('Johnny Depp', 'Helena Bonham Caster')
GROUP BY m.id, m.title
HAVING COUNT(*) = 2
i need to output all the movies that both "Johnny Depp" and "Helena Bonham Carter" starred. I think my problem is that I dont no what to putt inside of the WHERE
SELECT title
FROM movies JOIN
stars
ON movies.id = stars.movie_id JOIN
people ON stars.person_id = people.id
WHERE
this is what I got so far...
I would recommend moving the where clause into a query from one of the tables as it will be more efficient. Suppose your people table has a field called name then you could do a subquery like so:
SELECT stars.movie_id, people.name
FROM stars
JOIN (SELECT id, name FROM people WHERE name="Johnny Depp") AS people
ON people.id = stars.people_id
This gives all Johnny Depp movies, a similar query gives all Helena Bonham Carter movies. Now you can intersect the two queries:
SELECT stars.movie_id, people.name
FROM stars
JOIN (SELECT id, name FROM people WHERE name="Johnny Depp") AS people
ON people.id = stars.people_id
WHERE movie_id IN (SELECT stars.movie_id, people.name
FROM stars
JOIN (SELECT id, name FROM people WHERE name="Helena Bonham Carter") AS people
ON people.id = stars.people_id)
This gives all movies starring both. Now intersect this with your original query
SELECT
title
FROM movies
JOIN stars ON stars.movie_id = movies.id
JOIN people ON people.id = stars.person_id
WHERE starred_name IN ('Johnny Depp', 'Helena Bonham Carter')
-- i used "starred_name", becuase you never specified the name of the field.
my final cod was:
SELECT title
FROM people
JOIN stars ON people.id = stars.person_id
JOIN movies ON stars.movie_id = movies.id
WHERE movie_id IN (SELECT movie_id
FROM stars
JOIN people ON stars.person_id = people.id
WHERE name = "Helena Bonham Carter") and name = "Johnny Depp"
I need to find all the names of actors that have participated in more than 30 films. This below isn't quite doing it. What am I doing wrong here?
SELECT first_name, last_name
FROM actor A
WHERE 30 > (SELECT COUNT(actor_id) FROM film_actor);
Tables involved:
actor: actor_id first_name last_name last_update
film: film_id title description release_year language_id original_language_id rental_duration rental_rate length replacement_cost rating special_features last_update
film_actor: actor_id film_id last_update
Try this:
SELECT a.first_name, a.last_name
FROM actor a
INNER JOIN film_actor fa ON a.actor_id = fa.actor_id
GROUP BY a.actor_id, a.first_name, a.last_name
HAVING COUNT(fa.film_id) > 30
Behaviour explanation of your current query
Your current query runs without any connection between actor and film_actor tables, so the results would be odd and would actually show every actor from the actor table if the number of rows in entire film_actor table with non-null value actor_id is less than 30.
Right approach for the task
Use INNER JOIN with grouping and having clause to only show actors who participated in at least 30 movies.
If a pair of actor_id, film_id in your table film_actor is unique then this query would suffice:
SELECT a.actor_id,a.first_name, a.last_name
FROM actor a
INNER JOIN film_actor fa ON
a.actor_id = fa.actor_id
GROUP BY a.actor_id, a.first_name, a.last_name
HAVING COUNT(fa.film_id) > 30
However, if you are storing several roles an actor could play in a single movie, so that the pair mentioned earlier is not unique, then add distinct to the having clause:
HAVING COUNT(DISTINCT fa.film_id) > 30
Note that I've added actor_id to select and group by clause since two actors can have the same first and last name and you'd probably want to see those cases clearly.
use joined query instead try this
SELECT first_name, last_name
FROM actor a
JOIN actor_film af
ON(a.actor_id = af.actor_id)
WHERE (SELECT count(af.film_id) FROM af) > 30
This is also good alternative, if we have common columns then it would better to use only one in GROUP BY and rest of with aggregate function as like below:
SELECT
MAX(a.first_name) AS first_name,
MAX(a.last_name) AS last_name
FROM actor a
INNER JOIN film_actor fa ON a.actor_id = fa.actor_id
GROUP BY a.actor_id
HAVING COUNT(fa.film_id) > 30