SQL Query structure example for recursive lookup - sql

I'm struggling a bit with this query. Perhaps someone can give me a hint?
My setup consists of 3 tables (Actors, Movies, and Relations). What I want to do is:
Find all actors whose name starts with an A that play in any movie alongside Person1.
That's how far i got:
SELECT Name
FROM Actors a, Movies m, Relations r
WHERE a.Name='A%'
AND Person1.keyPerson = m.KeyPerson
AND m.KeyMovies ....
An example on how to continue would be nice!
UPADATE - tables look like this:
Actors (actorsID, name)
Movies (moviesID, title)
Relations (actorsID, moviesID)

There are several ways you can do this - one method you can do is via an IN statement, pulling the movies Person1 has been in, and checking the A% person's movies.
Select Distinct A.Name
From Actors A
Join Relations R On R.ActorId = A.ActorId
Where A.Name Like 'A%'
And R.MovieId In
(
Select R2.MovieId
From Actors A2
Join Relations R2 On R2.ActorId = A2.ActorId
Where A2.Name = 'Person1'
)
Another method is via an EXISTS statement, looking for any movies that Person1 has been in that A% has also been in:
Select A.Name
From Actors A
Join Relations R On R.ActorId = A.ActorId
Where A.Name Like 'A%'
And Exists
(
Select *
From Movies M2
Join Relations R2 On R2.MovieId = M2.MovieId
Join Actors A2 On R2.ActorId = R2.ActorId
Where A2.Name = 'Person1'
And M2.MovieId = R.MovieId
)

A solution without subquery:
SELECT DISTINCT a.Name
FROM Actors a
INNER JOIN Relations r
ON r.actorsID = a.actorsID
INNER JOIN Relations r2
ON r.moviesID = r2.moviesID
INNER JOIN Actors a2
ON a2.actorsID = r2.actorsID
AND a2.Name = 'Person1'
WHERE a.Name LIKE 'A%'

Related

SQL add attribute from another table

Table WORK
(WORK ID, TITLE, DESCRIPTION, ARTIST ID)
Table ARTIST
(ARTIST ID, FIRSTNAME, LAST NAME, DATE OF BIRTH, DATE OF DEATH)
Hi
My problem is that I have to display the details of all works of art (including the name of the artist who created the work) that are signed.
I managed to go until
Select * from Work WHERE DESCRIPTION LIKE '%Signed%'
and it displays
WorkID TITLE DESCRIPTION ARTISTID
123 1455 Signed 12
However, I must display
WorkID TITLE DESCRIPTION ARTISTID FIRSTNAME LASTNAME
123 1455 Signed 12
How do I do that? I know it has something to do with JOIN but I'm not very sure.
Inner Join will do or can try left join if u need to
SELECT W.*, A.FirstNAme, A.LastName from work w inner join Artist A on
A.Artistid
= W.ArtistId where A.Description LIKE '%Signed%'
Use inner join to get the records that exist in both tables
Select W.WorkID, W.TITLE, W.DESCRIPTION, W.ARTISTID, A.FIRSTNAME, A.LASTNAME
From Work W
Inner Join Artist A on W.WorkID = A.WorkID
Where Description LIKE '%Signed%'
a left outer join would get all the records in the work table and the matching ones in the artist table.
Check this post out to understand joins a bit more : JOINS

Oracle sql - referencing tables

My school task was to get names from my movie database actors which play in movies with highest ratings
I made it this way and it works :
select name,surname
from actor
where ACTORID in(
select actorid
from actor_movie
where MOVIEID in (
select movieid
from movie
where RATINGID in (
select ratingid
from rating
where PERCENT_CSFD = (
select max(percent_csfd)
from rating
)
)
)
);
the output is :
Gary Oldman
Sigourney Weaver
...but I'd like to also add to this select mentioned movie and its rating. It accessible in inner selects but I don't know how to join it with outer select in which i can work just with rows found in Actor Table.
Thank you for your answers.
You just need to join the tables properly. Afterwards you can simply add the columns you´d like to select. The final select could be looking like this.
select ac.name, ac.surname, -- go on selecting from the different tables
from actor ac
inner join actor_movie amo
on amo.actorid = ac.actorid
inner join movie mo
on amo.movieid = mo.movieid
inner join rating ra
on ra.ratingid = mo.ratingid
where ra.PERCENT_CSFD =
(select max(percent_csfd)
from rating)
A way to get your result with a slightly different method could be something like:
select *
from
(
select name, surname, percent_csfd, row_number() over ( order by percent_csfd desc) as rank
from actor
inner join actor_movie
using (actorId)
inner join movie
using (movieId)
inner join rating
using(ratingId)
(
where rank = 1
This uses row_number to evaluate the "rank" of the movie(s) and then filter for the movie(s) with the highest rating.

SQL: Join two different rows from the same table to a relation

Let's say I've got a table called relation with these fields:
id, type, person1.id, person2.id
Then there's the table with the people called person with this field:
id, name
Now I want to create a list that contains the following information:
relation.id, relation.type, person1.id, person1.name, person2.id, person2.name
How can I achieve this with an SQL statement? I know that this is probably a pretty basic question. :-(
You need to use the person table twice:
select rel.id, rel.type, p1.id, p1.name, p2.id, p2.name
from relation rel
, person p1
, person p2
where rel.person1 = p1.id
and rel.person2 = p2.id
Take a look at this
select relation.type,a.Person1_name,b.person2.name from relation inner join
(select relation.type, person1.name Person1_name from relation inner join person
on relation.person1=person.name
where person1 is not null)a
on relation.type=a.type
inner join
(
select relation.type, person2.name,from relation inner join person
on relation.person2=person.name
where person2 is not null)b
on relation.type=a.type
pls try this code

SQL looping through a table to count and group

I have a table like this
ID|list
1|:A:B:C:
2|:B:D:A:
3|:C:A:D:
I want to count the number of each of A,B,C,D and group them as
A|3
B|2
C|2
D|2
I was thinking about iterating through the table and inserting values in to a temporary table from count statements like the following
select count(*) from table where list like %:A:%
It does look ugly.Is there a better way to do this?
(I am using sqlite from qt)
Never, never, never store multiple values in one column! A better DB design would be
movies table
----------
id
name
release_date
...
actors table
------------
id
first_name
last_name
birth_date
...
movie_cast table
----------------
movie_id
actor_id
You could then select all actors of a specific movie like this
select a.lastName, a.first_name
from actors a
join movie_cast c on c.actor_id = a.id
join movies m on c.movie_id = m.id
where m.name = 'Citizen Kane'
Or select all movies a specific actor stars in like this
select m.name
from actors a
join movie_cast c on c.actor_id = a.id
join movies m on c.movie_id = m.id
where a.lastName ='Wayne'
and a.first_name 'John'

SQL select on a many-to-many table

I've got 3 tables: Movies, Actors, and MovieActors. MovieActors is a many-to-many relationship of Movies and Actors with columns MovieActorId, MovieId, and ActorId
How do I find movies that have a certain set of actors in it? For example I want to find all movies that have both Michael Fassbender (actor Id 1) and Brad Pitt (actor Id 2) in them. What would the query look like?
One way is to join the tables. Filter for the actors and then insure the count has the number of actors you want in it (2 in this case)
SELECT
m.MovieID
FROM
Movies m
INNER JOIN MovieActors ma
ON m.MovieID = ma.MovieID
WHERE
ma.ActorID IN (1,2)
GROUP BY
m.MovieID
HAVING COUNT(DISTINCT ma.ActorID) = 2
DEMO
Note
Thanks to user814064 for pointing out that since Actors can have more than one role on a movie we need to count the DISTINCT ma.ActorID not just * The SQL Fiddle Demo demonstrates the difference
select m.movieid
from movies m
inner join movieactors ma on ma.movieid = m.movieid
where ma.actorid in (1,2)
group by m.movieid
having count(distinct ma.actorid) = 2
To keep it simple, you can just do two in clauses:
select * from Movies m
where m.MovieId in (select MovieId from MovieActors where ActorId = 1)
and m.MovieId in (select MovieId from MovieActors where ActorId = 2)
Performance may not be as good as a single join, but it's clean and easy to read.