电影

2026 年的变更:5.sql 现在要求匹配以 “Harry Potter and the “ 开头的电影(不仅仅是 “Harry Potter”)。9.sql 现在要求输出两列(每个人的 ID 和名称),而不仅仅是名称。如果你在 2026 年之前开始做这个问题,请务必相应地更新你的查询!

IMDb Logo

要解决的问题

提供给你的是一个名为 movies.db 的 SQLite 数据库,该数据库存储来自 IMDb 的关于电影、导演和主演以及其评分的数据。编写 SQL 查询来回答关于此电影数据库的问题。

演示

入门

对于这个问题,你将使用 CS50 工作人员提供给你的一个数据库。

下载分发代码

登录 cs50.dev,点击你的终端窗口,然后只执行 cd。你应该会发现你的终端窗口的提示符类似于下面所示:

$

接下来执行

wget https://cdn.cs50.net/2026/x/psets/7/movies.zip

以便将一个名为 movies.zip 的 ZIP 文件下载到你的 codespace 中。

然后执行

unzip movies.zip

来创建一个名为 movies 的文件夹。你不再需要这个 ZIP 文件了,所以你可以执行

rm movies.zip

然后在提示符下回复”y”并按回车键来删除你下载的 ZIP 文件。

现在输入

cd movies

然后按回车键来将自己移入(即打开)该目录。你的提示符现在应该类似于下面所示。

movies/ $

只执行 ls,你应该看到 13 个 .sql 文件,以及 movies.db

如果遇到任何问题,再按照这些步骤试一次,看看你能不能找出哪里出错了!

规格说明

对于以下每个问题,你应编写一个单一的 SQL 查询,输出每个问题指定的结果。你的响应必须采用单个 SQL 查询的形式,尽管你可以在查询中嵌套其他查询。你不应假设任何特定电影或人物的 id 是什么:即使任何特定电影或人物的 id 不同,你的查询也应该是准确的。最后,每个查询应仅返回回答问题所需的数据:例如,如果问题只要求你输出电影的名称,那么你的查询不应同时输出每部电影的发行年份。

欢迎你将查询结果与 IMDb 本身进行核对,但要注意网站上的评分可能与 movies.db 中的评分不同,因为自从我们下载数据以来可能已经有更多投票!

  1. 1.sql 中,编写一个 SQL 查询来列出 2008 年发行的所有电影的标题。
    • 你的查询应输出一个表格,其中包含一列,为每部电影的标题。
  2. 2.sql 中,编写一个 SQL 查询来确定 Emma Stone 的出生年份。
    • 你的查询应输出一个表格,其中包含一列和一行(不计表头),包含 Emma Stone 的出生年份。
    • 你可以假设数据库中只有一个人名为 Emma Stone。
  3. 3.sql 中,编写一个 SQL 查询来列出 2018 年及之后发行的所有电影的标题,按字母顺序排列。
    • 你的查询应输出一个表格,其中包含一列,为每部电影的标题。
    • 2018 年发行的电影应包括在内,发行日期在未来的电影也应包括在内。
  4. 4.sql 中,编写一个 SQL 查询来确定 IMDb 评分为 10.0 的电影数量。
    • 你的查询应输出一个表格,其中包含一列和一行(不计表头),包含评分为 10.0 的电影数量。
  5. 5.sql 中,编写一个 SQL 查询来列出所有哈利波特电影的标题和发行年份,按时间顺序排列。
    • 你的查询应输出一个表格,其中包含两列,一列为每部电影的标题,一列为每部电影的发行年份。
    • 你可以假设所有哈利波特电影的标题将以 “Harry Potter and the “ 开头,并且如果电影标题以 “Harry Potter and the “ 开头,那么它就是一部哈利波特电影。
  6. 6.sql 中,编写一个 SQL 查询来确定 2012 年发行的所有电影的平均评分。
    • 你的查询应输出一个表格,其中包含一列和一行(不计表头),包含平均评分。
  7. 7.sql 中,编写一个 SQL 查询来列出 2010 年发行的所有电影及其评分,按评分降序排列。对于评分相同的电影,按标题字母顺序排列。
    • 你的查询应输出一个表格,其中包含两列,一列为每部电影的标题,一列为每部电影的评分。
    • 没有评分的电影不应包含在结果中。
  8. 8.sql 中,编写一个 SQL 查询来列出所有在 Toy Story 中出演的人的名称。
    • 你的查询应输出一个表格,其中包含一列,为每个人的名称。
    • 你可以假设数据库中只有一部电影标题为 Toy Story。
  9. 9.sql 中,编写一个 SQL 查询来列出所有在 2004 年发行的电影中出演的人的 ID 和名称,按出生年份排序。
    • 你的查询应输出一个表格,其中包含两列:一列为每个人的 ID,一列为每个人的名称。
    • 出生年份相同的人可以以任何顺序列出。
    • 无需担心没有列出出生年份的人,只要那些有出生年份的人按顺序列出即可。
    • 如果一个人在 2004 年出现在多于一部电影中,他们在你的结果中只应出现一次。
  10. 10.sql 中,编写一个 SQL 查询来列出所有导演过评分至少为 9.0 的电影的人的名称。
    • 你的查询应输出一个表格,其中包含一列,为每个人的名称。
    • 如果一个人导演了多于一部评分至少为 9.0 的电影,他们在你的结果中只应出现一次。
  11. 11.sql 中,编写一个 SQL 查询来列出 Chadwick Boseman 出演的五部评分最高的电影标题(按顺序),从评分最高的开始。
    • 你的查询应输出一个表格,其中包含一列,为每部电影的标题。
    • 你可以假设数据库中只有一个人名为 Chadwick Boseman。
  12. 12.sql 中,编写一个 SQL 查询来列出 Bradley Cooper 和 Jennifer Lawrence 都出演的所有电影的标题。
    • 你的查询应输出一个表格,其中包含一列,为每部电影的标题。
    • 你可以假设数据库中只有一个人名为 Bradley Cooper。
    • 你可以假设数据库中只有一个人名为 Jennifer Lawrence。
  13. 13.sql 中,编写一个 SQL 查询来列出所有在 Kevin Bacon 也出演的电影中出演的人的名称。
    • 你的查询应输出一个表格,其中包含一列,为每个人的名称。
    • 数据库中可能有多个名为 Kevin Bacon 的人。请务必只选择 1958 年出生的 Kevin Bacon。
    • Kevin Bacon 本人不应包含在结果列表中。

提示

理解 movies.db 的架构

每当接触一个新数据库时,最好首先理解它的架构。在终端窗口中,运行 sqlite3 movies.db,这样你就可以开始在数据库上执行查询了。

首先,当 sqlite3 提示你提供查询时,输入 .schema 并按回车键。这将输出用于生成数据库中每个表的 CREATE TABLE 语句。通过检查这些语句,你可以识别每个表中存在的列。

注意,movies 表有一个唯一标识每部电影的 id 列,以及用于电影 title 和电影发行 year 的列。people 表也有一个 id 列,还有用于每个人 namebirth 年份的列。

与此同时,电影评分存储在 ratings 表中。该表的第一列是 movie_id:一个引用 moviesid 的外键。行的其余部分包含有关每部电影 rating 的数据以及电影在 IMDb 上收到的 votes 数。

最后,starsdirectors 表将人物与他们出演或导演的电影匹配起来。(仅包含主要明星和导演。)每个表只有两列:movie_idperson_id,分别引用特定的电影和人物。

你面前的挑战是编写 SQL 查询,通过从这些表中的一个或多个中选择数据来回答各种不同问题。

一致地格式化你的查询

请参阅 sqlstyle.guide 了解 SQL 良好风格的指南,尤其是当你的查询变得更加复杂时!

列出 2008 年发行的所有电影的标题

回想一下,你可以使用 SELECT 从数据库中选择一列(或多列),如下例所示:

SELECT column0, column1 FROM table;

其中 column0 是一列的标题,column1 是另一列的标题。

再回想一下,你可以使用 WHERE 关键字后跟条件来过滤查询返回的行。你也可以使用 =><其他运算符

SELECT column FROM table
WHERE condition;

请参阅此 SQL 关键字参考了解一些可能有用的 SQL 语法!

确定 Emma Stone 的出生年份

回想一下,WHERE 子句不仅可以对数字,还可以对字符串评估条件。

列出 2018 年及之后发行的所有电影的标题,按字母顺序排列

尝试将此查询分解为两个步骤。首先,找到 2018 年及之后发行的电影。然后,将这些电影的标题按字母顺序排列。

要找到 2018 年及之后发行的电影,回想一下 SQL 中的条件支持使用许多常见的比较运算符,包括表示”大于或等于”的 >=。根据如何测试检查你的查询是否返回了正确数量的电影。

最后,按标题字母顺序对查询结果进行排序。回想一下 ORDER BY 可以按结果中的某一列对数据进行排序,如下例所示。

...
ORDER BY column;
确定 IMDb 评分为 10.0 的电影数量

注意此问题要求你提供的不是评分为 10.0 的个别电影,而是具有该评分的电影的数量。换句话说,你应该将查询结果收集(”聚合”)为单个数字(行数)。回想一下 SQL 支持一个名为 COUNT 的”聚合函数”,你可以在列上使用它,如下例所示。

SELECT COUNT(column)
FROM table;
列出所有哈利波特电影的标题和发行年份,按时间顺序排列

对于此查询,你可能想使用 SQL 的 LIKE 关键字。回想一下 LIKE 可以使用所谓的”通配符”,如 %,它将匹配任何字符(或字符序列)。

SELECT column0, column1
FROM table
WHERE column1 LIKE pattern;
确定 2012 年发行的所有电影的平均评分

这是另一个你需要聚合数据的查询示例。考虑使用 SQL 的 AVG 聚合函数来计算平均值。

还要考虑,此查询使用了存储在两个独立表中的数据:ratingsmovies。回想一下——只要一个表有一个与另一个表的列匹配的外键——你就可以使用 SQL 的 JOIN 关键字将两个表组合起来。要使用 JOIN 关键字,你应该指定要连接的表以及用来连接的列。

SELECT column0
FROM table0
JOIN table1 ON table0.column1 = table1.column2
列出 2010 年发行的所有电影及其评分,按评分降序排列

回想一下 ORDER BY 不必总是按升序排序。你可以通过附加 DESC 来指定结果按降序排序。

...
ORDER BY column DESC;
列出在 Toy Story 中出演的所有人的名称

当你看到像这样的更复杂的查询时,最好将其分解为更小的部分。最终,你的查询应得出一个名称列表,如下所示。

-- Select names
SELECT name
FROM people
WHERE ...

但如何最好地得出在 Toy Story 中出演的人的名称呢?考虑一下,仅凭 people 表没有此信息(但 stars 表可能有!)。实际上,stars 表组合了两列,person_idmovie_id:任何具有与 Toy Story 的 movie_id 相关联的 person_id 的人都在 Toy Story 中出演过。

-- Select names
SELECT name
FROM people
WHERE ...

-- Select person IDs
SELECT person_id
FROM stars
WHERE movie_id = ...

那么,自然的下一步就是查找 Toy Story 的电影 ID。

-- Select names
SELECT name
FROM people
WHERE ...

-- Select person IDs
SELECT person_id
FROM stars
WHERE movie_id = ...

-- Find Toy Story's ID
SELECT id
FROM movies
WHERE title = 'Toy Story';

当然,你现在已经编写了三个独立的查询。但请注意,某些查询(前两个)通过包含其正下方的查询结果就可以完成。制作依赖”子查询”结果的查询的过程称为”嵌套”查询。这是一个很大的提示,但以下是嵌套上述查询的一种方式!

-- Select names
SELECT name
FROM people
WHERE id IN
(
    -- Select person IDs
    SELECT person_id
    FROM stars
    WHERE movie_id = (

        -- Select Toy Story's ID
        SELECT id
        FROM movies
        WHERE title = 'Toy Story'
    )
);
列出所有在 2004 年发行的电影中出演的人的 ID 和名称,按出生年份排序

注意,这个查询与上一个类似,需要你使用来自多个表的数据。回想一下,你可以在 SQL 中“嵌套”查询,这使你可以将较大的查询分解为较小的查询。也许你可以编写查询来…

  1. 查找 2004 年发行的电影的 ID
  2. 查找在这些电影中出演的人的 ID
  3. 查找具有这些人员 ID 的人的 ID 和名称

然后,尝试嵌套这些查询以得出一个单一查询,该查询返回所有在 2004 年发行的电影中出演的人的 ID 和名称。考虑你如何然后对查询结果进行排序。

作为结束笔记,请记住多个人可以有相同的名称。虽然每个人应该只在你的结果中出现一次,但两个明星有相同的名称并不一定意味着他们是同一个人。

列出所有导演过评分至少为 9.0 的电影的人的名称

注意,这个查询与上一个类似,需要你使用来自多个表的数据。回想一下,你可以在 SQL 中“嵌套”查询,这使你可以将较大的查询分解为较小的查询。也许你可以编写查询来…

  1. 查找评分至少为 9.0 的电影的 ID
  2. 查找导演了这些电影的人的 ID
  3. 查找具有这些人员 ID 的人的名称

然后,尝试嵌套这些查询以得出一个单一查询,该查询返回所有导演过评分至少为 9.0 的电影的人的名称。

列出 Chadwick Boseman 出演的五部评分最高的电影标题(按顺序),从评分最高的开始

注意,这个查询与上一个类似,需要你使用来自多个表的数据。回想一下,你可以在 SQL 中“嵌套”查询,这使你可以将较大的查询分解为较小的查询。也许你可以编写查询来…

  1. 查找 Chadwick Boseman 的 ID
  2. 查找与 Chadwick Boseman 的 ID 相关联的电影的 ID
  3. 查找具有这些电影 ID 的电影标题

然后,尝试嵌套这些查询以得出一个单一查询,该查询返回 Chadwick Boseman 的电影标题。

从那里,你需要确定这些标题的评分,并按评分降序排列这些标题。考虑你如何组合一个相关的表(很可能是 ratings!)并按相关列对结果进行排序。

最后,阅读 SQL 的 LIMIT 关键字,它将返回查询中的前 n 行。

列出 Bradley Cooper 和 Jennifer Lawrence 都出演的所有电影的标题

注意,这个查询与上一个类似,需要你使用来自多个表的数据。回想一下,你可以在 SQL 中“嵌套”查询,这使你可以将较大的查询分解为较小的查询。也许你可以编写查询来…

  1. 查找 Bradley Cooper 的 ID
  2. 查找 Jennifer Lawrence 的 ID
  3. 查找与 Bradley Cooper 的 ID 相关联的电影的 ID
  4. 查找与 Jennifer Lawrence 的 ID 相关联的电影的 ID
  5. 从与 两者 Bradley Cooper 和 Jennifer Lawrence 相关联的电影 ID 中查找电影标题

然后,尝试嵌套这些查询以得出一个单一查询,该查询返回 Bradley Cooper 和 Jennifer Lawrence 都出演的电影。

回想一下,你可以在 SQL 中使用 ANDOR 构建复合条件。

列出所有在 Kevin Bacon 也出演的电影中出演的人的名称

注意,这个查询与上一个类似,需要你使用来自多个表的数据。回想一下,你可以在 SQL 中“嵌套”查询,这使你可以将较大的查询分解为较小的查询。也许你可以编写查询来…

  1. 查找 Kevin Bacon 的 ID(1958 年出生的那个!)
  2. 查找与 Kevin Bacon 的 ID 相关联的电影的 ID
  3. 查找与这些电影 ID 相关联的人的 ID
  4. 查找具有这些人员 ID 的人的名称

然后,尝试嵌套这些查询以得出一个单一查询,该查询返回所有在 Kevin Bacon 也出演的电影中出演的人的名称。请记住,你要将 Kevin Bacon 本人从结果中排除!

讲解视频

使用方法

要在 VS Code 中测试你的查询,你可以通过运行以下命令来查询数据库

$ cat filename.sql | sqlite3 movies.db

其中 filename.sql 是包含你的 SQL 查询的文件。

你也可以运行

$ cat filename.sql | sqlite3 movies.db > output.txt

将查询的输出重定向到一个名为 output.txt 的文本文件。(这对于检查你的查询返回了多少行很有用!)

如何测试

虽然 check50 可用于本问题,但我们鼓励你改为对以下每一项自行测试你的代码。你可以运行 sqlite3 movies.db 在数据库上运行额外查询,以确保你的结果是正确的。

如果你使用的是本问题集分发中提供的 movies.db 数据库,你应该发现

  • 执行 1.sql 会生成一个包含 1 列和 10,647 行的表格。
  • 执行 2.sql 会生成一个包含 1 列和 1 行的表格。
  • 执行 3.sql 会生成一个包含 1 列和 154,665 行的表格。
  • 执行 4.sql 会生成一个包含 1 列和 1 行的表格。
  • 执行 5.sql 会生成一个包含 2 列和 18 行的表格。
  • 执行 6.sql 会生成一个包含 1 列和 1 行的表格。
  • 执行 7.sql 会生成一个包含 2 列和 7,386 行的表格。
  • 执行 8.sql 会生成一个包含 1 列和 10 行的表格。
  • 执行 9.sql 会生成一个包含 2 列和 36,219 行的表格。
  • 执行 10.sql 会生成一个包含 1 列和 4,675 行的表格。
  • 执行 11.sql 会生成一个包含 1 列和 5 行的表格。
  • 执行 12.sql 会生成一个包含 1 列和 4 行的表格。
  • 执行 13.sql 会生成一个包含 1 列和 550 行的表格。

注意,行数不包括仅显示列名的表头行。

如果你的查询返回的行数与预期输出略有不同,请确保你正确处理了重复项!对于要求列出名称列表的查询,任何一个人都不应被列出两次,但两个有相同名称的不同人应该各自被列出。

正确性

check50 cs50/problems/2026/x/movies

如何提交

在终端中执行以下命令提交你的作业,并按提示完成操作。

submit50 cs50/problems/2026/x/movies

致谢

信息由 IMDb (imdb.com) 提供。 经许可使用。