SQLZOO #12 -- 对多个 select 和连接语句感到困惑

SQLZOO #12 -- confused about multiple select & join statements

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

12:'John Travolta' 最忙的年份是哪一年,显示他制作超过 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. Actor 仅与 Movie 连接,还是与 Movie JOIN Casting[=33] 连接的演员=]?
  2. 我试图找到一个解释复杂连接语句的网站,因为我尝试的答案远非正确(缺少许多部分)。我认为带有多个复杂连接语句的 subselect 语句目前有点混乱。但是,我找不到一个好的网站来分解信息来帮助我形成自己的查询。

我不完全理解的另一部分是:

 (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。上面的代码试图找到什么?

正确答案是:

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 网站上的一个错误)正在寻找计数等于计数最高年份的任何年份。

我在上面的查询中使用了 table 别名来弄清楚 table 是如何连接的。电影与演员结合,演员与演员结合。

让您感到困惑的子查询列出了每年和约翰特拉沃尔塔主演的那一年的电影数量。如果您按书面回答问题,则不需要。

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

好的,很高兴你不怕问,我会尽力帮助澄清发生了什么......请原谅我重新格式化查询以适应我编写查询的心态。它更好地显示了事物来源的关系(我的观点),并且也可能对您有所帮助。

关于我重写的其他一些事情。我还喜欢使用对 table 的别名引用,这样每一列都可以使用它所源自的 table(或别名)进行限定。它可以防止歧义,特别是对于不了解您的 table 结构和 table 之间关系的人。 (m = 电影的别名,c = 演员的别名,a = 演员的别名 tables)。对于子查询,为了避免别名混淆,我在它们后面加上了 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 查询。查看它,看看 IT 将交付什么。如果你 运行 那,你会得到他每年都有一部电影和电影的数量......他们的样本数据的起始结果从 1976 年一直到 2010 年。到目前为止,没有什么复杂的(大约20 行)。现在,由于每个 table 可能有一个别名,每个子查询(例如这个必须有一个别名,所以这就是 "as t" 的原因。所以,没有真正的 table,它正在包装整个查询的结果集并分配 "t".

的别名

所以现在,在查询中向上一级也包含在括号中...

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

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

现在,对于最外层的查询...同样,这实际上与最内层的查询相同。唯一的区别是 HAVING 子句。这在执行了每年的所有分组之后应用。然后它将每年的 IT 行结果集计数与 SELECT MAX( t.movieCount )...

的 3 值结果进行比较

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

现在,澄清 JOIN。每个 table 应该与一个或多个 table 有关系(也称为链接 table,例如演员表 table 既有电影又有 actors/actresses。因此,将连接想象成我如何按顺序排列 table,以便每个人都可以接触到另一个,直到我将它们全部链接在一起。在这种情况下

Movie -> Casting 通过电影 ID 链接,然后 Casting -> actor 通过演员 ID,这就是我在视觉上分层的方式...我从电影开始 table,加入演员表 table 基于电影 ID = 演员表电影 ID。现在,从 Casting table 加入到 Actor table 基于公共 Actor ID 字段

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

现在,这是一个简单的关系,但是您可以有一个主要 table 和多个子级 table。您可以根据各自的数据加入多个 table。非常简单的示例来阐明这一点。您有一个学生 table 正在上学。一个学生有一个学位专业、一个种族、一个地址州(假设一个在线学校和学生可以来自任何州)。如果您查找 table 的学位、种族和州,您可能会想出类似...

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

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

因此,那里有很多网站,例如 Mark 提供的 w3schools,但要学会一次剖析小块......从点上得到的最低限度 tables 是多少-A 到点-Z 并绘制关系。然后,根据您正在寻找的要求标准进行处理。