retrieve data from movie database - sql

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

Related

Relational Division in SQL

Writing a SQL query to list the fullname ('<first_name> <last_name>') of every actor who acted in every film which had a title starting with 'CHOCOLAT':
Here is my approach:
SELECT
actor_id, first_name || ' ' || last_name AS fullname
FROM
Actor A
WHERE
NOT EXISTS (SELECT film_id
FROM Film F
WHERE title LIKE 'CHOCOLAT%'
EXCEPT
SELECT film_id
FROM Film_Actor FA
WHERE FA.actor_id = A.actor_id)
ORDER BY
fullname
The problem with this approach is that when there is no film which had a title starting with 'CHOCOLAT%', it lists all the actors instead of returning an empty table.
The query selects the matching films and removes for each actor the film that the actor acts in. If a film remains, the actor is not acting in the film so he must not be present in the final result.
SELECT actor_id,
first_name || ' ' || last_name AS fullname
FROM Actor A
WHERE NOT EXISTS(SELECT film_id
FROM Film F
WHERE title LIKE 'CHOCOLAT%' -- select all matching films
EXCEPT
SELECT film_id
FROM Film_Actor FA
WHERE FA.actor_id = A.actor_id -- remove the films the actor acts in
) -- have a set of films the actor does not act in
-- if there is no matching film the actor does not act in,
-- (i.e. he acts in all of them) he needs to be selected
and (SELECT count(film_id)
FROM Film F
WHERE title LIKE 'CHOCOLAT%') > 0
-- special case, when there is no matching film at all:
-- The list of films the actor does not act in would be empty for every actor
-- Thus, the result would be all actors
ORDER BY fullname;
Basically, you could just add another if-clause that requires at least one matching film to be present. You could do this with count() > 0 or exists(...).

At most one query SQL

I'm doing some exercises in a basic SQL and I have the following problem:
Let us consider the following relational schema about actors and films:
Film: FilmCode đŸ”‘, Title, Filmmaker, Year
Actor: ActorCode đŸ”‘, Surname, Name, Sex, BirthDate, Nationality
Interpretation: Film, Actor, Role
Let us assume that more than one actor may act in a film and that the same actor may act in more than one film and in a given film, each involved actor plays only one role.
Filmmaker to be univocally identified by his/her surname and each film to be directed by a single filmmaker.
The query I have to write is:
the actors that acted together in at most one film directed by the filmmaker Quentin Tarantino.
How can I translate the "at most one film" into SQL language?
What I have wrote so far is:
SELECT DISTINCT A1.ActorCode, A2.ActorCode
FROM Actor A1 A2, Interpretation I1 I2
WHERE I1.Film=I2.Film and I1.Actor <> I2.Actor and A1.ActorCode= I1.Actor and A2.ActorCode=I2.ActorCode and exists unique (
Select *
From Film F
Where I1.Film=F.FilmCode and F.Filmmaker=’Tarantino’
)
But that's not the point
SELECT
I.Actor, I2.Actor
FROM Interpretation I
INNER JOIN FIlm F
ON F.Filmmaker=’Tarantino’
and F.FilmCode = I.Film
INNER JOIN Interpretation I2
ON I.Film = I2.Film
and I2.Actor <> I.Actor
and I2.Actor not in (SELECT Actor
FROM Interpretation I3
INNER JOIN FIlm F1
ON F1.Filmmaker=’Tarantino’
and F1.FilmCode = I3.Film
and F1.FilmCode <> I.Film #All other tarantino films
WHERE I3.Actor = I.Actor)

Nesting SELECT statements with duplicate entries and COUNT

I'm working with 3 tables: actors, films, and actor_film. Actors and films only have 2 fields: id (primary key) and name. Actor_film also has 2 fields, actor and film, which are both foreign keys representing actor and film ids, respectively. So if a film had 4 actors in it, there'd be 4 actor_film entries with the same film and 4 different actors.
My problem is that, given a certain actor's id, I'd like to return the actor id, actor name, film name, and the total number of actors in that film. However, the only actors that I want to show are ones that contain certain letters in their names.
Let me clear things up with an example. Say Tom Hanks is in only 2 movies, Forrest Gump and Saving Private Ryan, and I'm looking for actors in those 2 movies that have "Gary" or "Matt" in their names. Further suppose that there are 4 actors in Forrest Gump, and 5 in Saving Private Ryan. Then, the only thing I'd want to return would be (without the column names, of course)
actor id | actor name | film name | # actors
abcdefg | Gary Sinise | Forrest Gump | 4
hijklmn | Matt Damon | Saving Private Ryan | 5
opqrstu | Paul Giamatti | Saving Private Ryan | 5
Currently, I'm 75% of the way there by using:
SELECT actor.id, actors.name, films.name,
FROM (
SELECT actor_film.film
FROM actor_film, actors
WHERE actor_film.actor = actors.id
) AS a, actor_film, actors, films
WHERE actor_film.film = a.film
AND actors.id = actor_film.actor
AND films.id = a.film;
This is returning stuff like:
arnie | Arnold Schwarzenegger | Around the World in 80 Days
arnie | Arnold Schwarzenegger | Around the World in 80 Days
for a film that has 2 actors in it. In other words, I can't pull out all the distinct actors in the movie, but get the proper count for it implicitly and not explicitly with COUNT.
Anyway, I think I'm looking for some kind of INNER JOIN or nested SELECT, but I'm new to SQLite3 and don't know how to bring these together. Any solutions would be great, and any explanations on top of that would be amazing as well.
You shouldn't use the old style joins. They were old in '95 when the newer standard that let you do left joins clearer was made a standard.
I've noticed you also use plurals for your table names (eg "actors") The standard style is to use the singular for the table table name (eg "actor")
I use both these suggestions below, I also show you each step. I suggest you run the queries for each step and look at the output to understand how everything works since you are new to SQL.
Ok, lets take you problem step by step. First of all to see each actor and the films they are in (your first 3 columns) do this:
SELECT a.id as actor_id, a.name as actor_name, f.name as film_name
FROM actor as a
JOIN actor_film af on a.id = af.actor
JOIN film as f on af.film = f.id
Your last column can be found with the following query:
SELECT af.film as film_id, count(*) as c
FROM actor_film as af
GROUP BY af.film
Now we just join them together
SELECT a.id as actor_id, a.name as actor_name, f.name as film_name, fc.c as num_actors
FROM actor as a
JOIN actor_film af on a.id = af.actor
JOIN film as f on af.film = f.id
JOIN (
SELECT af.film as film_id, count(*) as c
FROM actor_file as af
GROUP BY af.film
) as fc on af.film = fc.film_id
If you want you can add a
WHERE a.name = 'Gary' OR a.name = 'Matt'
depending on your platform you might want
WHERE lower(a.name) = 'gary' OR lower(a.name) = 'matt'

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'))

SQL query that finds the names of the actors who are playing in "Action" genre

I am doing a small course in SQL during my academic degree, I am very new with this material.
Given database of the website "eMovies" that manage data about cinema movies.
Write in SQL query that finds the names of the actors who are playing in "Action" genre and that the actor Johnny Depp does not playing is those movies.
The tables:
Actors
ActorID PK
Firstname
LastName
Directors
DirectorID PK
Firstname
LastName
Genres
GenreID PK
GenreDescr
Movies
MovieID PK
MovieName
Year
ActorsMovies
MovieID PK
ActorID PK
DirectorsMovies
MovieID PK
DirectorID PK
GenresMovies
MovieID PK
GenreID PK
My attempt:
SELECT Actors.FirstName,Actors.LastName
FROM Actors
INNER JOIN ActorsMovies ON Actors.ActorID= ActorsMovies.ActorID
INNER JOIN GenresMovies ON ActorsMovies.MovieID=GenresMovies.MovieID
GROUP BY GenreID
HAVING GenreID='201' AND NOT IN Actors.ActorID='301855124' ;
Did you try this?
SELECT Actors.FirstName,Actors.LastName
FROM Actors
INNER JOIN ActorsMovies ON Actors.ActorID= ActorsMovies.ActorID
INNER JOIN GenresMovies ON ActorsMovies.MovieID=GenresMovies.MovieID
WHERE GenreID='201' AND Actors.ActorID<>'301855124' ;
SELECT Actors.FirstName,Actors.LastName
FROM Actors
INNER JOIN ActorsMovies t ON Actors.ActorID= t.ActorID
INNER JOIN GenresMovies ON t.MovieID=GenresMovies.MovieID
WHERE GenresMovies.GenreID = 201 and
not exists (select b.movieid from actorsmovies b where b.ActorID=301855124 and b.movieid = t.movieid) ;
This query uses NOT EXISTS function that checks in each actor that answer your request that johnny depp doesn't play in that movie