selected statement in joining table - sql

movie:
id ,title,yr,director,budget,gross
actor:
id,name
casting:
movieid,actorid,ord
I have a question on this I has been asking to (List the films together with the leading star for all 1962 films.) [Note: the ord field of casting gives the position of the actor. If ord=1 then this actor is in the starring role]
My answer was this:
select
title, name
from
movie
join
casting on movie.id = casting.movieid
join
actor on actor.id = casting.actorid
where
yr = 1962 and movie.id = casting.movieid and actor.id = casting.actorid and casting.ord = 1
group by
title
But what my problem was I can get close to the answer, I have the problem at the ord part because some of the casting do not have 1 for the actor that just showing two, so it will not display on the output.
How could I make it select ord =1 or ord =2 (but not both)(and 1 have higher priority)
Hope anyone can help me this.

select title,coalesce (c.name,c21.name) as actorname from movie m
left join (select * from casting where ord=1) c on m.id= c.movieid
left join (select * from casting where ord=2) c1 on c.movieid = c1.movieid
left join actor a on a.id= c.actorid
where yr=1962

Hope this will output your expected result
Select title,name
From Movie M
Cross Apply (Select top 1 movieid,actorid,ord from Casting Order By ord) as Cast
Inner join Actor A On A.id = Cast. actorid

Use CROSS APPLY (http://technet.microsoft.com/en-us/library/ms175156(v=sql.105).aspx) with a subquery which is ordered by the 'ord' column and has a TOP(1) clause.
SELECT
M.title
, CA.name
FROM
movie AS M
CROSS APPLY (
SELECT TOP(1)
actor.name
FROM
casting C
INNER JOIN actor A
ON C.actorid = A.id
WHERE
M.id = C.movieid
ORDER BY
ord
ASC
) AS CA

I have 2 answers:
SELECT movie.title, (select actor.name from actor where actor.id = casting.actorid)
FROM movie
JOIN casting
ON movie.id =casting.movieid
WHERE movie.yr = 1962 and casting.ord = 1
But then I realized that you can chain joins:
SELECT movie.title, actor.name
FROM movie
JOIN casting ON movie.id=casting.movieid
JOIN actor ON casting.actorid = actor.id
WHERE movie.yr = 1962 and casting.ord = 1
The second one is clearly much simpler. (There's no need to nest a SELECT statement).
To have it select either or, do ... and (casting.ord = 1 xor casting.ord = 2).
To order it by 1, try something like Order by casting.ord in (1,2). (I haven't tested that.

Related

(SQL ZOO) Lead actor in Julie Andrews movies

SQL Zoo
https://sqlzoo.net/wiki/More_JOIN_operations
No. 12:
Lead actor in Julie Andrews movies
List the film title and the leading actor for all of the films 'Julie Andrews' played in.
Did you get "Little Miss Marker twice"?
Julie Andrews starred in the 1980 remake of Little Miss Marker and not the original(1934).
Title is not a unique field, create a table of IDs in your subquery (What does this mean?)
What I wrote was this but it says I'm wrong, don't know why:
SELECT title, name
FROM (movie JOIN casting ON movie.id = casting.movieid) JOIN actor ON actor.id = casting.actorid
WHERE title IN
(SELECT title FROM casting JOIN actor ON casting.actorid = actor.id
where actor.name = 'Julie Andrews')
AND ord = 1
WHERE title IN
(SELECT title FROM casting JOIN actor ON casting.actorid = actor.id
where actor.name = 'Julie Andrews')
There is no title column in either casting or actor. So you have accidentally correlated this subquery - the title is scoped from outside the subquery so you effectively have something like
where 1 in
(select 1
from casting JOIN actor ON casting.actorid = actor.id
where actor.name = 'Julie Andrews'
)
Which will be true if that subquery returns any rows. Always be clear which row source a column should come from.
You probably meant to select the movieid column from casting and use that as a filter against movie.id similar to your join in the first subquery:
SELECT movie.title, actor.name
FROM movie
JOIN casting ON movie.id = casting.movieid
JOIN actor ON actor.id = casting.actorid
WHERE movie.id IN
(SELECT casting.movieId FROM casting JOIN actor ON casting.actorid = actor.id
where actor.name = 'Julie Andrews')
AND casting.ord = 1
Had a quick go, this goes the trick
/* Create a derived table of the relevant IDs*/
with j as (
select movieid
from casting c join actor a on a.id=c.actorid
where a.name='julie andrews'
)
/*
Now use this as a starting point to join to the
relevant tables to fetch the required actors from
the movieIDs from the derived table
*/
select m.title, a.name
from j join movie m on m.id=j.movieid
join casting c on c.movieid=j.movieid
join actor a on a.id=c.actorid
where c.ord=1

Select statement returns the incorrect results

I have been trying to figure out the correct SQL for question number 13 in this tutorial. None of the other questions concern me, just #13.
Essentially, what the question asks is to find out all the movies that 'Julie Andrews' played in, and from that result, select the actors who played the leading actors in those movies. Sounds simple enough, but everything I try is failing. The following:
select title, name from movie
join casting on movie.id=movieid
join actor on actorid=actor.id
where (name = 'Julie Andrews' )
and ord=1
selects the movies that she was in and she was the lead actor. What I need is the lead actors for movies she was in, not the movies she played the lead in.
Does anyone have any suggestions?
select movie.title, actor.name
from movie, actor, casting, (SELECT movieid from casting join actor
on actor.id=casting.actorid where actor.name = 'Julie Andrews') JAM
where movie.id = JAM.movieid and actor.id = casting.actorid
and casting.movieid=JAM.movieid and casting.ord=1
group by movie.title
Try this:
select m.title, a.name
from movie m
join casting c on m.id = c.movieid
and ord = 1
join actor a on a.id = c.actorid
where exists (select *
from casting c2
join actor a2 on c2.actorid = a2.id
and a2.name = 'Julie Andrews'
where c2.movieid = m.id
)

SQLzoo | JOIN operation

I'm trying to solve question 13 of JOIN tutorial in SQLzoo (http://sqlzoo.net/wiki/More_JOIN_operations)
The question ask to list the film title and the leading actor for all of the films 'Julie Andrews' played in.
I've produced the following script, but somewhere is wrong.
SELECT title, actor.name FROM
movie JOIN casting ON movie.id=movieid
JOIN actor ON actor.id=actorid
WHERE ord=1
AND title = ALL
(SELECT title FROM
movie JOIN casting ON movie.id=movieid
JOIN actor ON actor.id=actorid
WHERE actor.name='Julie Andrews')
The right script is:
SELECT m.title,
a.name
FROM movie m
JOIN casting c
ON m.id = c.movieid
AND c.ord = 1
JOIN actor a
ON a.id = c.actorid
WHERE m.id IN (SELECT m1.id
FROM movie m1
JOIN casting c1
ON m1.id = c1.movieid
JOIN actor a1
ON a1.id = c1.actorid
WHERE a1.name = 'Julie Andrews')
I've noticed that if I'm using the column m.title as a proxy in the WHERE statement the script takes more time to run and the SQLzoo server stop it. Instead, using the m.id column makes things faster to load. Perhaps is a good practice always prefer to check digits instead of letters when possible.
Another issue on my initial scripts was setting an EQUAL operator instead of IN. The sub-query returns more than 1 row, thus is necessary the use of an IN operator.
Try this :
SELECT title, name
FROM movie, casting, actor
WHERE movieid=movie.id
AND actorid=actor.id
AND ord=1
AND movieid IN
(SELECT movieid FROM casting, actor
WHERE actorid=actor.id
AND name='Julie Andrews')
Easy Solution:
select movie.title, actor.name FROM movie
JOIN casting
ON casting.movieid = movie.id
JOIN actor
ON actor.id = casting.actorid
where ord = 1 and
movieid in (select movieid from casting join actor on id = actorid where name = 'Julie Andrews' )
I think this is the right way to you get it.
SELECT m.title, a.name FROM
movie m JOIN casting c ON c.id = m.movieid
JOIN actor a ON a.id=m.actorid
WHERE m.ord=1
AND m.title = ALL
(SELECT m1.title FROM
movie m1 JOIN casting c1 ON c1.id=m1.movieid
JOIN actor a1 ON a1.id=m1.actorid
WHERE a1.name='Julie Andrews');
If you have to display your tables with column names then i will be modify this query
select title, name from movie
join casting on (casting.movieid =movie.id)
join actor on (actor.id = casting.actorid)
where ord =1
and movieid in (select movie.id from movie
join casting on (casting.movieid =movie.id)
join actor on (actor.id = casting.actorid)
where name = 'Julie Andrews')
SELECT title,name
FROM movie
JOIN casting ON (movieid=movie.id AND ord=1)
JOIN actor ON (actor.id=actorid)
WHERE movieid IN (SELECT movieid
FROM movie
JOIN casting ON (movieid=movie.id)
JOIN actor ON (actor.id=actorid)
WHERE actor.name='Julie Andrews')
Starting from subquery: Select all the 'movieid' of movies with 'Julie Andrews' in them and use it as a filter in WHERE
Now join all the 3 tables with a specific condition that you only select the 'actorid' with 'ord'=1 ('ord'=1 means that the actors name is on top of order of actors). This will only select the rows/records containing the actor ids of lead actors. In the end just retrieve these leading actors name from 'actor' table.
SELECT title,name FROM
casting join movie on movie.id=movieid and ord=1
join actor on actor.id=actorid
WHERE movie.id in (
SELECT movie.id FROM
movie join casting on movie.id=movieid
join actor on actor.id=actorid
WHERE name='Julie Andrews' )

sql : join and group by

Having 3 tables:
movie(id, title, yr, score, votes,
director) actor(id, name)
casting(movieid, actorid, ord)
Q:Which were the busiest years for
'John Travolta'. Show the number of
movies he made for each year.
A: My try is syntactically worng. why ?
select yr, count(*)
from
(actor join casting
on (actor.id = casting.actorid)
join
on (movie.id = casting.movieid)
group by yr
having actor.name='John Travolta'
You are missing the second table name after join
use where not having
Try this:
select yr, count(*)
from actor
join casting on actor.id = casting.actorid
join movie on movie.id = casting.movieid -- you were missing table name "movie"
where actor.name='John Travolta' -- "where", not "having"
group by yr
Also note the consistent formatting I used. If you use a good format, it's easier to find syntax errors
FYI, having is used for aggregate functions, eg having count(*) > 3
Remove the ( ) from around the table name and add movie to your second join.
select yr, count(*)
from actor join
casting on actor.id = casting.actorid join
movie on movie.id = casting.movieid
group by yr
having actor.name='John Travolta'
EDIT:
You need to switch your having to a where because havings are use for aggregate functions in conjunctions with your group by.
select yr, count(*)
from actor join
casting on actor.id = casting.actorid join
movie on movie.id = casting.movieid
where actor.name = 'John Travolta'
group by yr
To join u have to specify table ure joining, should be
join movie
on movie.id = casting.movieid

again new query. i am trying to solve this from one hour. please help

Query : List the film title and the leading actor for all of 'Julie Andrews' films.
there are three tables
movie (id, title, yr, score, votes, director)
actor (id, name)
casting (movieid, actorid, ord)
select movie.title,actor.name as cont
from movie
join casting on (movie.id=casting.movieid)
join actor on (casting.actorid=actor.id)
where actor.name='Julie andrews'
actually i can't get how to find the leading actor.
You almost for sure will need a sub query to achieve this one way or another.
select movie.title, actor.name
from movie
inner join casting
on movie.id = casting.movieid
and casting.ord = 1 --Assuming this is the cast order flag
inner join actor
on casting.actorid = actor.id
where movie.id in (
select movie.id
from movie
inner join casting
on movie.id = casting.movieid
and casting.actorid = {your actorID in this case Julie Andrew's id
)
Disclaimer: I didn't test this as you didn't provide an easy way to do so.
If you really wanted to go by name (which could lead to false positive) then you can add an extra join to the in clause sub query.
Firstly, you shouldn't use id for the key column, use movieid and actorid. This makes joins easier:
select movie.title, lead.name as cont
from actor
join casting using (actorid)
join movie using (movieid)
join casting as leadrole using (movieid)
join actor as lead on (leadrole.actorid = lead.actorid)
where actor.name = 'Julie andrews'
and leadrole.ord = 1
This assumes that the lead actor's ord column is 1. It is also completely untested, so you will probably need to debug it.
Assuming the lead role is ord = 1 you can try this out (I didn't test it)
EDIT:
select
M.title,
(select
A1.name
from
casting CI
join
actors A1
on
A1.id = CI.actorid
where
CI.movieid = M.id
and
CI.ord = 1) as LeadingActor
from
movie M
join
casting C
on
M.id = C.movieid
join
actor A
on
C.actorid = A.id
where
A.name='Julie andrews'