How do I list the first value from a three-way joi

2019-04-15 12:54发布

问题:

Ugh ok I'm terrible at explaining things, so I'll just give you the quotes and links first:

Problem 4b (near bottom):

4b. List the film title and the leading actor for all of 'Julie Andrews' films.

movie(id, title, yr, score, votes, director)
actor(id, name)
casting(movieid, actorid, ord)
(Note: movie.id = casting.movieid, actor.id = casting.actorid)

My answer (doesn't work):
    SELECT title, name
      FROM casting JOIN movie
              ON casting.movieid = movie.id
      JOIN actor
              ON casting.actorid = actor.id
     WHERE name = 'Julie Andrews'
       AND ord = 1

The problem here is that it wants the list of lead actors of movies with 'Julie Andrews' as an actor (who is not necessarily the lead actor), but all I'm doing with my answer is getting the movies where she is the lead (ord = 1).

How do I specify the list of lead actors without 'Julie Andrews' being it? I suspect I have to do something with GROUP BY, but I can't figure out what at the moment...

Edit: Do I need to use a nested SELECT?

回答1:

There are wonderful ways of doing this with subqueries, but it appears that t this point in the tutorial you're only working with JOINs. The following is how you would do it with only JOINs:

SELECT
  movie.title,
  a2.name
FROM
  actor AS a1
  JOIN casting AS c1 ON (a1.id = c1.actorid)
  JOIN movie ON (c1.movieid = movie.id)
  JOIN casting AS c2 ON (movie.id = c2.movieid)
  JOIN actor AS a2 ON (c2.actorid = a2.id)
WHERE 
  a1.name = 'Julie Andrews'
  AND c2.ord = 1

EDIT (more descriptive):

This will give us a table containing all of the movies Julie Andrews acted in. I'm aliasing the actor and casting tables as a1 and c1 respectively because now that we've found a list of movies, we'll have to turn and match that against the casting table again.

SELECT
  movie.*
FROM
  actor a1
  JOIN casting c1 ON (a1.id = c1.actorid)
  JOIN movie ON (c1.movieid = movie.id)
WHERE
  a1.name = 'Julie Andrews'

Now that we have a list of all movies she acted, we need to join that against the casting table (as c2) and that to the actor table (as a2) to get the list of leading roles for these films:

SELECT
  movie.title,  -- we'll keep the movie title from our last query
  a2.name       -- and select the actor's name (from a2, which is defined below)
FROM
  actor a1                                     -- \
  JOIN casting AS c1 ON (a1.id = c1.actorid)   --  )- no changes here
  JOIN movie ON (c1.movieid = movie.id)        -- /
  JOIN casting AS c2 ON (movie.id = c2.movieid)  -- join list of JA movies to the cast
  JOIN actor AS a2 ON (c2.actorid = a2.id)  -- join cast of JA movies to the actors
WHERE 
  a1.name = 'Julie Andrews'  -- no changes
  AND c2.ord = 1    -- only select the star of the JA film

Edit: In aliasing, the 'AS' keyword is optional. I've inserted it above to help the query make more sense



回答2:

You want to match movies to two potentially separate rows in the casting table: one row where Julie Andrews is the actor, and the second row which may or may not be Julie Andrews, but which is the lead actor for the film.

Julie <---> cast in <---> a movie <---> starring <---> Lead actor

So you need to join to the casting table twice.

SELECT m.title, lead.name
FROM actor AS julie
 JOIN casting AS c1 ON (julie.id = c1.actorid)
 JOIN movie AS m ON (c1.movieid = m.id)
 JOIN casting AS c2 ON (m.id = c2.movieid)
 JOIN actor AS lead ON (c2.actorid = lead.id)
WHERE julie.name = 'Julie Andrews'
 AND c2.ord = 1;

Remember that "table aliases" reference potentially different rows, even if they are aliases to the same table.



回答3:

SELECT title, name
      FROM casting JOIN movie
              ON casting.movieid = movie.id
      JOIN actor
              ON casting.actorid = actor.id
     WHERE ord = 1
     and   casting.movieid in 
          (select movieid
           from   casting
                  join actor
                      on actor.id = casting.actorid
           where  actor.name = 'Julie Andrews')


回答4:

By the way, this was the answer posted on the site (I just found out about it):

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

Go figure. :P



回答5:

select title, name  from movie join casting on movie.id=movieid
join actor on actor.id=actorid 
where ord=1 and movieid in (select movieid from actor join casting 
                                            on actor.id=actorid 
         where name='julie andrews' and (ord=1 or ord<>1))group by title, name


回答6:

@Bill Karwin 's answer is good for the direction. However, the result turns out some movies' title has been appear more than one time. So we need added a DISTINCT function before title in SELECT row.

SELECT DISTINCT m.title, lead.name

And if you want more quick response, you also could write code in this way.

SELECT DISTINCT m.title, lead.name
 FROM actor AS julie
  JOIN casting AS c1 ON (julie.id = c1.actorid AND julie.name = 'Julie Andrews')
  JOIN movie AS m ON (c1.movieid = m.id)
  JOIN casting AS c2 ON (m.id = c2.movieid)
  JOIN actor AS lead ON (c2.actorid = lead.id)
 WHERE  c2.ord = 1;


回答7:

I ve done simply like this

select distinct title,name from 
(select movie.* from movie
inner join casting on (movie.id = casting.movieid)
inner join actor on (casting.actorid = actor.id)
where actor.name = 'Julie Andrews' ) as moviesFromJulie

inner join casting on (moviesFromJulie.id = casting.movieid)
inner join actor on (casting.actorid = actor.id)
where ord = 1

Retreive all movies julie andrews played in, then for those movies retreive all movies and actors for them with ordinal number = 1, and distinct for unique results



回答8:

Sharing an easy answer to this-

select title, name from movie join casting on movie.id=movieid join actor on actor.id=actorid where ord=1 and movie.id in (select movie.id from movie join casting on movie.id=movieid join actor on actor.id=actorid where name='Julie Andrews')



回答9:

SELECT title , name
FROM movie JOIN casting ON (casting.movieid=movie.id) JOIN actor ON (actor.id=actorid)
WHERE (movieid IN (SELECT movieid
FROM casting JOIN actor ON (actor.id=actorid)
WHERE name =  'Julie Andrews')) AND (ord=1)