At most one query SQL - 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)

Related

A self join query

Given this relational schema
people (pid, name, gender, age, email, city, state)
books (ISBN, title, edition, publisher, year, rating)
write (pid, ISBN) pid is a foreign key and refers to people (pid), ISBN is a foreign key and refers to books (ISBN)
I need to write a SQL query to find the authors who either never published co-authored books or only co-authored with others from the same state, return their names.
I know I need to use a self join but not sure how to do that.
Thanks!
I think Tim's reasoning is correct, but the query is not. It requires a self-join on writes:
select p.*
from people p
where not exists (select 1
from writes w join
writes w2
on w.isbn = w2.isbn join
people p2
on w2.pid = w.pid
where w.pid = p.pid and
p.state <> p2.state
);
Your two logical criteria can actually be condensed into saying that you only want authors who have not coauthored books with other from different states. So, we can write a query for that:
SELECT p1.name
FROM people p1
WHERE NOT EXISTS (SELECT 1 FROM write w INNER JOIN people p2 ON p2.pid = w.pid
WHERE w.pid = p1.pid AND p2.state <> p1.state);

improving the sql query for a dbms problem

I want to write a SQL query for the problem as defined below, my answer for the first part is as below, but I am not sure about the answer, can anyone help me? Is the answer correct, or if not, how can I improve it?
For the second part can anyone help me?
Let us consider the following relational schema about physicians and departments:
PHYSICIAN (PhysicianId, Name, Surname, Specialization, Gender, BirthDate, Department);
Let every physician be univocally identified by a code and characterized by a name, a surname, a specialization (we assume to record exactly one specializa- tion for each physician), a gender, a birth date, a department (each physician is assigned to one and only one department), and a home city.
Let every city be univocally identified by its name and characterized by the region it belongs to.
DEPARTMENT (Name, Building, Floor, Chief)
Let every department be univocally identified by a name and characterized by its location (building and floor) and chief. Let us assume that a physician can be the chief of at most one department (the department he/she belongs to). We do not exclude the possibility for two distinct departments to be located at the same floor of the same building.
BELONGS TO(City,Region)
Let us assume that a physician can be the chief of at most one department (the department he/she belongs to). We do not exclude the possibility for two distinct departments to be located at the same floor of the same building.
I want to formulate an SQL query to compute the following data (exploiting aggregate functions only if they are strictly necessary):
• the departments such that (i) all their physicians reside in the region Piemonte and (ii) at least one of them resides in the city Torino.
My answer for the fist part is as below:
for the second part, I don't know how to solve it .
create view X{
select b.city, b.region, b.department
from physician p inner join belong-to b on b.city= p.homecity
where b.region="Piemonte"
select name
from department d
where exists( select*
from X
where p.department =d.name )
I think this should work:
Select Distinct b.department
From physician p
Join belong-to b on b.city = p.homecity
Where Exists (Select 1 From belong-to b2 Where b2.city = p.homecity AND b2.region = "Piemonte")
Exists (Select 1 From belong-to b2 Where b2.city = p.homecity AND b2.city = "Torino") AND
NOT Exists (Select 1 From belong-to b2 Where b2.city = p.homecity AND b2.region <> "Piemonte") AND
I would use aggregation:
select p.department
from physician p join
belongsto b
on p.homecity = b.city
group by p.department
having sum(case when b.region <> 'Piemonte' then 1 else 0 end) = 0 and -- no Piemonte
sum(case when p.homecity = 'Torino' then 1 else 0 end) >= 1 -- at least one Torino

SQL query to filter value using associative entity

I'm working on this educational system in which the professor table stores the subject ID, career and subject are stored in their own tables and I have the career_subject associative entity because the system assume that the same subject may belong to several careers. The tables look something like this:
CAREER(id, name, quota)
SUBJECT(id, name, exam_date)
PROFESSOR(id, name, subject_id)
CAREER_SUBJECT(career_id, subject_id)
So, how do I get the name of the career the professor may teach using SQL?
I'm trying with
SELECT name FROM career
INNER JOIN career_subject ON career_subject.subject_id = career_subject.subject_id
WHERE professor.subject_id = subject.id;
SELECT p.name as 'Professor', c.name as 'Career' FROM professor p
INNER JOIN career_subject cs ON cs.subject_id = p.subject_id
INNER JOIN career c ON c.id = cs.career_id

SQL can't group by... Options?

I have the next tables:
involved_in represents a relation between a movie and a person who worked in it:
FID AID JOB
---------- ---------- -----------------------------------
2387816 226673 actor
2146284 230306 actor
1814529 233362 actor
2146710 275818 actor
2033140 324419 actor
2387816 452297 actor
1749641 522815 actor
2379685 972581 actor
2384487 1001930 actor
2065098 1021573 actor
is_a represents a relation between two movies as in movie a is a prequel to movie b:
MOVID1 MOVID2 REL_ID
---------- ---------- ----------
2455766 1858631 2
2465356 716238 12
2465467 1005316 2
2465585 2046499 1
2465793 1992318 6
2465793 2144984 5
2467514 1984530 15
In other tables I can get titles and names for the id's used above.
I want to find those pairs actor-director that have worked more than x times together in movies that are not related as in Johnny Depp has worked with Tim Burton in movies that are not related.
The problem comes with the x times and my really small database account which won't let me have big enough temp tables.
I can:
create view friends as
(select actor, director, film, count(*) over (PARTITION BY actor, director) as together
from
(select a.aid as actor, b.aid as director, a.fid as film
from involved_in a, involved_in b
where a.fid=b.fid AND (a.job='actor' or a.job='actress') AND b.job='director'));
And that will give me every actor-director pair, every film they've worked in together and how many times they have worked together.
The view is too big so I could start by removing all those pairs that have worked less than x times together. Using group by actor, director gets me an error in film (not a group by expression).
Is there any way to limit the rows that appear with count less than x? I've also tried
having count(...) > x
It would be perfect if I could count(actor, director) but that's not the syntax of course since it would be convenient.
After getting my friends view I'm using this query:
select f1.actor, f1.director
from friends f1, friends f2, is_a
where f1.actor = f2.director and f2.actor = f1.director and NOT (f1.film = movid1 and f2.film = movid2);
I don't use JOIN ON and such because my teacher said they were redundant though I do think it looks better so maybe I will use them eventually.
Any ideas?
I suggest the following query, with some major tweaks to yours and removed redundancy.
Use explicit JOINs for better readability, and IN clause to save some space in code. Planner will translate this clause anyways.
CREATE VIEW friends AS
SELECT
actor, director, film, num_together
FROM(
SELECT
a.aid AS actor,
b.aid AS director,
a.fid AS film,
COUNT(*) OVER (PARTITION BY a.aid, b.aid) AS num_together
FROM
involved_in a
INNER JOIN involved_in b ON
a.fid = b.fid
WHERE
a.job IN ('actor', 'actress')
AND b.job = 'director'
) foo
WHERE
num_together < 'x' -- placeholder for your "limit the rows that appear with count less than x"
Though, this view may be misleading, as it lists the number of times which actor and director worked together, but it appears right next to every film they did work on together.
You already have nested select statements, just add another one:
create view friends as
(
SELECT actor, director, film, together
FROM (
select actor, director, film, count(*) over (PARTITION BY actor, director) as together
from
(
select a.aid as actor, b.aid as director, a.fid as film
from involved_in a
INNER JOIN involved_in b ON(a.fid=b.fid)
WHERE (a.job='actor' or a.job='actress')
AND b.job='director'
) InnerMostQuey
) MiddleQuery
WHERE together > x -- Replace x with whatever number that makes you happy :-)
);

sql select actors play two more distinct role in the same movie

the question is to select actors that played 2 or more distinct roles in the same movie.
And I got 3 table, actor (id,name) movie (id,name) and casts(aid,mid,role) (aid is the actor id and mid is the movie id)
I wrote a query like this
select a.name
from actor a, movie m, casts c
where a.id = c.aid and m.id = casts.mid
group by (m.name)
having count(distinct role) > 2;
this didnt print the right result and I didnt see the problem with it.
Thanks for the help!
How about this? Was there any error trying to execute your query?
select actor.name from actor, casts, movie
where casts.aid =actor.id
and casts.mid = movie.id
group by movie.name, actor.name
having count(distinct role) >= 2
As the casts table appears to contain one row per actor, movie, and role (unless you are leaving out other columns), any time a single pair of unique values of aid and mid appears on more than one row, it means the actor played more than one role in that movie. Thus, there is no reason to use distinct. Also because your desired result doesn't contain the movie names, your query doesn't need and shouldn't use the movie table.
If it is true that the cast table has only one row for each unique combination of (aid, mid, and role) then the following should work:
select name
from actor
where id in ( select aid
from casts
group by aid, mid
having count(*) > 1)