SQLZOO#12 - 混淆了多个选择&加入陈述

时间:2015-05-21 02:30:03

标签: sql join subquery

我试图回答sqlzoo.net上的问题#12 (http://sqlzoo.net/wiki/More_JOIN_operations)。我无法自己找出答案,但我确实设法在网上找到答案。

12:约翰特拉沃尔塔的最繁忙的年份,展示了他每年制作超过2部电影的年份和电影数量。

答案:

SELECT yr,COUNT(title) FROM
  movie JOIN casting ON movie.id=movieid
         JOIN actor   ON actorid=actor.id
WHERE name='John Travolta'
GROUP BY yr  
HAVING COUNT(title)=(SELECT MAX(c) FROM
(SELECT yr,COUNT(title) AS c FROM
   movie JOIN casting ON movie.id=movieid
         JOIN actor   ON actorid=actor.id
 WHERE name='John Travolta'
 GROUP BY yr)  AS t)

我不完全理解的部分之一是多连接:

 FROM movie 
 JOIN casting ON movie.id=movieid
 JOIN actor   ON actorid=actor.id
  1. 演员仅与电影合并,还是演员加入电影加入
  2. 我正在尝试找到一个解释复杂连接语句的网站,因为我的尝试答案远非正确(缺少许多部分)。我认为具有多个复杂连接语句的子选择语句目前有点令人困惑。但是,我找不到一个打破信息的好网站,以帮助我形成自己的问题。
  3. 我不完全理解的另一部分是:

     (SELECT yr,COUNT(title) AS c FROM
           movie JOIN casting ON movie.id=movieid
                 JOIN actor   ON actorid=actor.id
         WHERE name='John Travolta'
         GROUP BY yr)  AS t)
    

    3。上面的代码试图找到什么?

2 个答案:

答案 0 :(得分:0)

正确的答案是:

SELECT yr, COUNT(title)
FROM movie m
JOIN casting c ON m.id=c.movieid JOIN actor a ON c.actorid=a.id 
WHERE name='John Travolta' 
GROUP BY yr 
HAVING COUNT(title) > 2;

你找到的答案(这似乎是sqlzoo网站上的一个错误)正在寻找任何一年的计数等于最高计数的年份。

我在上面的查询中使用了表别名来清除表的连接方式。电影加入了铸造,铸造加入了演员。

让您感到困惑的子查询每年都会列出,以及约翰特拉沃尔塔明星那一年的电影数量。如果您以书面形式回答问题,则不需要它。

关于学习资源,请确保您掌握了基础知识。了解http://w3schools.com/sql处的所有内容。当你准备好了更多时,尝试在你最喜欢的搜索引擎中搜索“sql join multiple tables”。

答案 1 :(得分:0)

好的,很高兴你不要害怕,我会尽力帮助澄清发生的事情......请原谅我将查询重新格式化为写作查询的心态。它更好地展示了事物来源的关系(我的观点),也可以帮助你。

关于我的重写的一些其他事情。我还想使用对表的别名引用,以便每个列都使用它所源自的表(或别名)进行限定。它可以防止歧义,尤其是对于不了解表结构和表之间关系的人。 (m =电影的别名,c =投射的别名,a =演员表的别名)。对于子查询,并保持别名混淆清晰,我用2加上后缀,如m2,c2,a2。

SELECT
      m.yr,
      COUNT(m.title) 
   FROM
      movie m
         JOIN casting c
            ON m.id = c.movieid
            JOIN actor a
               ON c.actorid = a.id
   WHERE 
      a.name = 'John Travolta'
   GROUP BY 
      m.yr  
   HAVING 
      COUNT(m.title) = ( SELECT MAX(t.movieCount) 
                          FROM
                             ( SELECT m2.yr,
                                      COUNT(m2.title) AS movieCount
                                  FROM
                                     movie m2
                                        JOIN casting c2
                                           ON m2.id = c2.movieid
                                           JOIN actor a2
                                              ON c2.actorid = a2.id
                                  WHERE 
                                     a2.name='John Travolta'
                                  GROUP BY 
                                     m2.yr )  AS t
                     )

首先,查看最外面的查询(别名m,c,a),最里面的查询(别名m2,c2,a2)实际上是相同的。

查询必须首先从最深的查询运行...在这种情况下是m2,c2,a2查询。看看它,看看它将提供什么。如果你运行它,你每年都会得到一部电影和电影的数量......他们的样本数据的起始结果从1976年一直到2010年。到目前为止,没有任何复杂的东西(大约20行)。现在,由于每个表都可能有一个别名,每个子查询(例如这个必须有一个别名,所以这就是“as t”。所以,没有真正的表,它包装整个查询的结果集并分配这是别名“t”。

所以现在,在查询中提高一级也包含在parens ......

SELECT MAX(t.movieCount)
   FROM (EntireSubquery as t)

虽然缩写,但这就是引擎正在做的事情。查看子查询结果,给出别名“t”并找到最大“movieCount”值,该值是给定年份内完成的电影数量。在这种情况下,实际数字是3,我们差不多完成了。

现在,对于最外层的查询......再次,这几乎与最里面的查询相同。唯一的区别是HAVING子句。在执行每年的所有分组之后应用此选项。然后它将每年的IT行结果集计数与SELECT MAX的3值结果进行比较(t.movi​​eCount)......

因此,所有只有1或2部电影的年份都被排除在结果之外,只有一年有3部电影被包括在内。

现在,澄清一下JOIN。每个表应该与一个或多个表有关系(也称为链接表,例如同时具有电影和演员/演员的演员表。因此,请考虑连接,如何将表按顺序排列,以便每个人都能碰到另一个,直到我把它们全部链接在一起。在这种情况下

电影 - >通过电影ID链接的转换,然后是Casting - >演员身份角色扮演者,这就是我在视觉上分层次地做的...我从电影表开始,根据电影ID =演员电影ID加入演员表。现在,从Casting表加入到基于公共Actor ID字段的Actor表

   FROM
      movie m
         JOIN casting c
            ON m.id = c.movieid
            JOIN actor a
               ON c.actorid = a.id

现在,这是一个简单的关系,但是你可以有一个包含多个子级表的主表。您可以根据相应的数据连接多个表。非常简单的样本澄清了这一点。你有一张学生桌去学校。学生拥有学位专业,种族,地址状态(假设在线学校,学生可以来自任何州)。如果您有关于度,种族和状态的查找表,您可能会想出类似......

的内容
select
      s.firstname,
      s.lastname,
      d.DegreeDescription,
      e.ethnicityDescription,
      st.stateName
   from
      students s
         join degrees d
            on s.degreemajor = d.degreeID
         join ethnicity e
            on s.ethnicityID = e.id
         join states st
            on s.homeState = st.stateID

请注意每个表在学生的表下直接关联的层次结构表示。并非所有表都需要比最后一个表更深。

所以,那里有很多网站,比如Mark提供的w3schools,但是学会一次解剖小块...从A点到Z点的最小表是什么?画出关系。然后,根据您正在寻找的要求标准去掉。