【问题标题】:How do I list the first value from a three-way joined table query?如何列出三向连接表查询中的第一个值?
【发布时间】:2009-01-11 23:31:50
【问题描述】:

呃,好吧,我不擅长解释事情,所以我先给你引用和链接:

Problem 4b(接近底部):

4b。列出所有“朱莉·安德鲁斯”电影的片名和男主角。

电影(id、标题、年份、分数、票数、导演)
演员(ID,姓名)
cast(movieid, actorid, ord)
(注意:movie.id = cast.movi​​eid, actor.id = cast.actorid)

我的回答(不起作用):
    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

这里的问题是,它想要以“朱莉·安德鲁斯”为演员(不一定是主角)的电影的主要演员名单,但我所做的只是让她的电影是领先(ord = 1)。

如果没有“朱莉·安德鲁斯”,我如何指定主要演员名单?我怀疑我必须对 GROUP BY 做点什么,但我现在不知道是什么...

编辑:我需要使用嵌套的 SELECT 吗?

【问题讨论】:

  • 您将在我的回答中看到,子查询(嵌套 SELECT)不是必需的。它使查询更具可读性,但完全可以不这样做。
  • 问题:这样做是否更有效率(我的意思是,而不是子查询)?
  • @Daddy Warbox:这取决于。通常不会,但通常成本相同。
  • @Daddy Warbox:这令人困惑!我的意思是,通常直接连接更有效,但通常子选择会被优化为相同或相似的查询执行计划。
  • 是的,这就是我要问的。谢谢。我会记住这一点的。

标签: mysql sql mysql-5.0


【解决方案1】:

使用子查询有很多很好的方法,但在本教程的这一点上,您似乎只使用 JOIN。以下是仅使用 JOIN 的方法:

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

编辑(更具描述性):

这将为我们提供一个表格,其中包含 Julie Andrews 出演的所有电影。我将演员表和演员表分别别名为 a1 和 c1,因为现在我们已经找到了电影列表,我们必须转身,再次将其与施法台相匹配。

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'

现在我们有了她演过的所有电影的列表,我们需要将其与演员表(如 c2)和演员表(如 a2)相结合,以获得这些电影的主角列表:

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

编辑:在别名中,'AS' 关键字是可选的。我在上面插入了它以帮助查询更有意义

【讨论】:

  • 在迄今为止的条目中,这是避免子查询的最明确的条目,如果这是解决方案的标准,但是,正如您所指出的,围绕子查询版本更容易让您的大脑思考。
  • 编辑得更具描述性。在查询中多次连接一个表并不罕见,这就是别名派上用场的原因。希望我的修改对您有所帮助。
  • 认为我明白。稍后,当我首先阅读有关别名的内容时,我将重新阅读此内容。虽然我想我已经明白了。
【解决方案2】:

您希望将电影与casting 表中的两个可能独立的行进行匹配:第一行是 Julie Andrews 是演员,第二行可能是也可能不是 Julie Andrews,但它是电影。

朱莉参演电影主演男主角

所以你需要加入casting 表两次。

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;

请记住,“表别名”引用可能不同的行,即使它们是同一个表的别名。

【讨论】:

    【解决方案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】:

      顺便说一句,这是网站上发布的答案(我刚刚发现):

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

      去图吧。 :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 的回答有利于方向。 然而,结果证明有些电影的名字已经出现了不止一次。 所以我们需要在 SELECT 行的 title 前添加一个 DISTINCT 函数。

          SELECT DISTINCT m.title, lead.name
          

          如果你想要更快速的响应,你也可以这样写代码。

          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
            

            检索朱莉·安德鲁斯出演的所有电影,然后为这些电影检索序数 = 1 的所有电影和演员,并为独特的结果而区分

            【讨论】:

              【解决方案8】:

              分享一个简单的答案-

              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)
                

                【讨论】:

                  猜你喜欢
                  • 2019-08-09
                  • 2023-01-29
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-05-02
                  • 2015-09-23
                  • 2013-07-13
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多