Relational Division in SQL - 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(...).

Related

SQL query column does not exist

New to SQL here. I tried WITH clause today and can't figure out why I get an error from my query.
Table structure
CREATE TABLE actor
(
actor_id
first_name
last_name
last_update
)
CREATE TABLE film_actor
(
actor_id
film_id
last_update
)
CREATE TABLE film
(
film_id
title
release_year
rating
)
Query that causes the error:
WITH tempotable(actorwithid) AS
(
SELECT
actor.actor_id, first_name, last_name,film_id
FROM
actor
LEFT OUTER JOIN
film_actor ON actor.actor_id = film_actor.actor_id
WHERE
first_name = 'Nick'
AND last_name = 'Wahlberg'
)
SELECT
title, film.film_id, first_name, last_name, actor_id
FROM
film
LEFT OUTER JOIN
tempotable ON film.film_id = tempotable.film_id
ORDER BY
film_id
I can get desired outcome if I switch second left outer join table but I also want actor_id column in my final outcome. After add extra SELECT actor_id in second join, an error: column "actor_id" does not exist pop up. But actor_id column suppose the first column in the tempotable.
I tried tempotable.actor_id still same error.
This is a question from Udemy online sql lessons. Very appreciate for any help!

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)

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

Count number of ID in relation and connect to name in PostgreSQL

I have three tables: films, actors and the relationship actors_film.
I'm trying to decide which actors has been in the most number of movies. If the actor has been in a movie this is shown with actor_id(primary key).
I figured I want to count the number of times each actor_id shows in the table film_actor for each film_id, and then connect this with the right name(actor.first_name).
I've got the first part down, but can't seem to connect the Count-value to the right name.
SELECT actor_id, COUNT(*) AS number_of_films
FROM film_actor
GROUP by actor_id
ORDER by 2
DESC limit 1;
How would I go forward connecting the actors name from the actor-table?
I'm thinking I need some form of:
WHERE actor.actor_id = film_actor.actor_id.
You need a simple inner join between the table actors and the table actors_film:
SELECT a.actor_name, a.actor_id, COUNT(*)
FROM actors a INNER JOIN actors_films af
ON a.actor_id = af.actor_id
GROUP BY a.actor_name, a.actor_id
ORDER BY 3;

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