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

待解决的问题 (Problem to Solve)
为你提供了一个名为 movies.db 的文件,这是一个 SQLite 数据库,存储了来自 IMDb 的关于电影、导演、演员及其评分的数据。编写 SQL 查询来回答有关此电影数据库的问题。
演示 (Demo)
入门 (Getting Started)
对于这个问题,你将使用由 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。
如果你遇到任何困难,请再次按照这些步骤操作,看看能否找出出错的地方!
规范 (Specification)
对于以下每个问题,你应该编写一个单独的 SQL 查询,并输出每个问题指定的结果。你的回答必须采用单个 SQL 查询的形式,不过你可以在查询中嵌套其他查询。你 不应该 对任何特定电影或人的 id 做任何假设:即使任何特定电影或人的 id 不同,你的查询也应该是准确的。最后,每个查询应该只返回回答问题所必需的数据:例如,如果问题只要求你输出电影的名称,那么你的查询就不应该同时输出每部电影的发行年份。
欢迎你对照 IMDb 本身来检查查询结果,但请注意,网站上的评分可能与 movies.db 中的不同,因为自我们下载数据以来可能有更多人参与了投票!
在
1.sql中,编写一个 SQL 查询,列出 2008 年发行的所有电影的标题。- 你的查询应输出一张表,其中只有一列,显示每部电影的标题。
在
2.sql中,编写一个 SQL 查询,确定 Emma Stone 的出生年份。- 你的查询应输出一张表,其中包含单列单行(不包括表头),包含 Emma Stone 的出生年份。
- 你可以假设数据库中只有一个名叫 Emma Stone 的人。
在
3.sql中,编写一个 SQL 查询,按字母顺序列出 2018 年或之后发行的所有电影的标题。- 你的查询应输出一张表,其中只有一列,显示每部电影的标题。
- 2018 年发行的电影应该包括在内,将来发行的电影也应包括在内。
在
4.sql中,编写一个 SQL 查询,确定 IMDb 评分为 10.0 的电影数量。- 你的查询应输出一张表,其中包含单列单行(不包括表头),包含评分为 10.0 的电影数量。
在
5.sql中,编写一个 SQL 查询,按时间顺序列出所有《哈利·波特》(Harry Potter)系列电影的标题和发行年份。- 你的查询应输出一张具有两列的表,一列是每部电影的标题,另一列是每部电影的发行年份。
- 你可以假设所有《哈利·波特》电影的标题都以 “Harry Potter and the ” 开头,并且如果一部电影的标题以 “Harry Potter and the ” 开头,它就是一部《哈利·波特》电影。
在
6.sql中,编写一个 SQL 查询,确定 2012 年发行的所有电影的平均评分。- 你的查询应输出一张表,其中包含单列单行(不包括表头),包含平均评分。
在
7.sql中,编写一个 SQL 查询,列出 2010 年发行的所有电影及其评分,按评分降序排列。对于评分相同的电影,按标题的字母顺序排列。- 你的查询应输出一张具有两列的表,一列是每部电影的标题,另一列是每部电影的评分。
- 不具有评分的电影不应包含在结果中。
在
8.sql中,编写一个 SQL 查询,列出所有参演《玩具总动员》(Toy Story)的人的姓名。- 你的查询应输出一张表,其中只有一列,显示每个人的姓名。
- 你可以假设数据库中只有一部标题为 Toy Story 的电影。
在
9.sql中,编写一个 SQL 查询,列出所有参演 2004 年发行的电影的人的 ID 和姓名,按出生年份排序。- 你的查询应输出一张具有两列的表:一列是 ID,另一列是每个人的姓名。
- 出生年份相同的人可以按任何顺序排列。
- 无需担心没有列出出生年份的人,只要列出了出生年份的人按顺序排列即可。
- 如果一个人在 2004 年出演了多部电影,他们应该只在你的结果中出现一次。
在
10.sql中,编写一个 SQL 查询,列出所有执导过评分为 9.0 或更高的电影的人的姓名。- 你的查询应输出一张表,其中只有一列,显示每个人的姓名。
- 如果一个人执导了多部评分为 9.0 或更高的电影,他们应该只在你的结果中出现一次。
在
11.sql中,编写一个 SQL 查询,列出 Chadwick Boseman 参演的评分最高的五部电影(按顺序),从评分最高的开始。- 你的查询应输出一张表,其中只有一列,显示每部电影的标题。
- 你可以假设数据库中只有一个名叫 Chadwick Boseman 的人。
在
12.sql中,编写一个 SQL 查询,列出 Bradley Cooper 和 Jennifer Lawrence 两人都参演过的所有电影的标题。- 你的查询应输出一张表,其中只有一列,显示每部电影的标题。
- 你可以假设数据库中只有一个名叫 Bradley Cooper 的人。
- 你可以假设数据库中只有一个名叫 Jennifer Lawrence 的人。
在
13.sql中,编写一个 SQL 查询,列出所有参演过凯文·贝肯(Kevin Bacon)也参演过的电影的人的姓名。- 你的查询应输出一张表,其中只有一列,显示每个人的姓名。
- 数据库中可能有多个名叫 Kevin Bacon 的人。请务必仅选择 1958 年出生的那个 Kevin Bacon。
- Kevin Bacon 本人应不包括在生成的列表中。
提示 (Hints)
理解 movies.db 的模式 (schema)
每当你接触一个新的数据库时,最好先了解它的 模式 (schema)。在终端窗口中,运行 sqlite3 movies.db,以便你可以开始在数据库上执行查询。
首先,当 sqlite3 提示你提供查询时,输入 .schema 并按回车。这将输出用于生成数据库中每个表的 CREATE TABLE 语句。通过检查这些语句,你可以识别每个表中存在的列。
请注意,movies 表有一个 id 列,用于唯一标识每部电影,还有 title 列(电影标题)和 year 列(电影发行年份)。people 表也有一个 id 列,还有每个人的 name(姓名)和 birth(出生年份)列。
同时,电影评分存储在 ratings 表中。该表的第一列是 movie_id:一个引用 movies 表 id 的外键。行的其余部分包含有关每部电影的 rating(评分)和该电影在 IMDb 上收到的 votes(投票数)的数据。
最后,stars 和 directors 表将人与他们参演或导演的电影相匹配。(仅包括主要演员和导演。)每个表只有两列:movie_id 和 person_id,它们分别引用特定的电影和人。
摆在你面前的挑战是编写 SQL 查询,通过从一个或多个表中选择数据来回答各种不同的问题。
保持一致的查询风格
有关 SQL 中良好风格的建议,请参阅 sqlstyle.guide,特别是当你的查询变得更加复杂时!
列出 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;
确定评分为 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 聚合函数来计算平均值。
此外,还要考虑此查询使用了存储在两个独立表中的数据:ratings 和 movies。回想一下,只要一个表具有与另一个表中的列匹配的外键,你就可以使用 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 name
FROM people
WHERE ...
但是如何最好地获得参演过 Toy Story 的人的姓名呢?考虑一下,people 表本身没有这些信息(但 stars 表可能有!)。事实上,stars 表结合了两列,person_id 和 movie_id:任何具有与 Toy Story 的 movie_id 关联的 person_id 的人都参演了 Toy Story。
-- 选择姓名
SELECT name
FROM people
WHERE ...
-- 选择人员 ID
SELECT person_id
FROM stars
WHERE movie_id = ...
那么,自然而然的下一步就是找到 Toy Story 的电影 ID。
-- 选择姓名
SELECT name
FROM people
WHERE ...
-- 选择人员 ID
SELECT person_id
FROM stars
WHERE movie_id = ...
-- 查找 Toy Story 的 ID
SELECT id
FROM movies
WHERE title = 'Toy Story';
当然,你目前编写了三个 独立 的查询。但请注意,某些查询(前两个)可以通过包含其正下方查询的结果来完成。制作依赖于 “子查询” 结果的查询的过程称为 “嵌套” 查询。这是一个很大的提示,但这里有一种嵌套上述查询的方法!
-- 选择姓名
SELECT name
FROM people
WHERE id IN
(
-- 选择人员 ID
SELECT person_id
FROM stars
WHERE movie_id = (
-- 选择 Toy Story 的 ID
SELECT id
FROM movies
WHERE title = 'Toy Story'
)
);
列出所有参演 2004 年发行的电影的人的 ID 和姓名,按出生年份排序
请注意,此查询与前一个查询一样,需要你使用来自多个表的数据。回想一下,你可以在 SQL 中 “嵌套” 查询,这允许你将较大的查询分解为较小的查询。也许你可以编写查询来……
- 查找 2004 年发行的电影的 ID
- 查找参演这些电影的人员的 ID
- 查找具有这些人员 ID 的人员的 ID 和姓名
然后,尝试嵌套这些查询,以得到一个返回所有在 2004 年发行的电影中出演的人员 ID 和姓名的单个查询。考虑之后如何对查询结果进行排序。
最后要注意的是,请记住多个人可以有相同的名字。虽然每个人应该只在你的结果中出现一次,但两个明星名字相同并不一定意味着他们是同一个人。
列出所有执导过评分为 9.0 或更高的电影的人的姓名
请注意,此查询与前一个查询一样,需要你使用来自多个表的数据。回想一下,你可以在 SQL 中 “嵌套” 查询,这允许你将较大的查询分解为较小的查询。也许你可以编写查询来……
- 查找评分至少为 9.0 的电影的 ID
- 查找执导过这些电影的人员的 ID
- 查找具有这些人员 ID 的人员的姓名
然后,尝试嵌套这些查询,以得到一个返回所有执导过评分为 9.0 或更高的电影的人员姓名的单个查询。
列出 Chadwick Boseman 参演的评分最高的五部电影(按顺序)的标题,从评分最高的开始
请注意,此查询与前一个查询一样,需要你使用来自多个表的数据。回想一下,你可以在 SQL 中 “嵌套” 查询,这允许你将较大的查询分解为较小的查询。也许你可以编写查询来……
- 查找 Chadwick Boseman 的 ID
- 查找与 Chadwick Boseman 的 ID 关联的电影 ID
- 查找具有这些电影 ID 的电影标题
然后,尝试嵌套这些查询,以得到一个返回 Chadwick Boseman 电影标题的单个查询。
从那里开始,你需要确定这些标题的评分,并按评分降序排列这些标题。考虑如何结合相关表(很可能是 ratings!)并按相关列对结果进行排序。
最后,阅读 SQL 的 LIMIT 关键字,它将返回查询中的前 \(n\) 行。
列出 Bradley Cooper 和 Jennifer Lawrence 两人都参演过的所有电影的标题
请注意,此查询与前一个查询一样,需要你使用来自多个表的数据。回想一下,你可以在 SQL 中 “嵌套” 查询,这允许你将较大的查询分解为较小的查询。也许你可以编写查询来……
- 查找 Bradley Cooper 的 ID
- 查找 Jennifer Lawrence 的 ID
- 查找与 Bradley Cooper 的 ID 关联的电影 ID
- 查找与 Jennifer Lawrence 的 ID 关联的电影 ID
- 从与 Bradley Cooper 和 Jennifer Lawrence 关联的电影 ID 中查找电影标题
然后,尝试嵌套这些查询,以得到一个返回 Bradley Cooper 和 Jennifer Lawrence 两人都参演过的电影的单个查询。
回想一下,你可以在 SQL 中使用 AND 或 OR 构建复合条件。
列出所有参演过凯文·贝肯(Kevin Bacon)也参演过的电影的人的姓名
请注意,此查询与前一个查询一样,需要你使用来自多个表的数据。回想一下,你可以在 SQL 中 “嵌套” 查询,这允许你将较大的查询分解为较小的查询。也许你可以编写查询来……
- 查找 Kevin Bacon 的 ID(1958 年出生的那个!)
- 查找与 Kevin Bacon 的 ID 关联的电影 ID
- 查找与这些电影 ID 关联的人员 ID
- 查找具有这些人员 ID 的人员的姓名
然后,尝试嵌套这些查询,以得到一个返回所有参演过 Kevin Bacon 也参演过的电影的人员姓名的单个查询。请记住,你需要从结果中排除 Kevin Bacon 本人!
演练 (Walkthrough)
用法 (Usage)
要在 VS Code 中测试你的查询,你可以通过运行以下命令来查询数据库:
$ cat filename.sql | sqlite3 movies.db
其中 filename.sql 是包含你的 SQL 查询的文件。
你也可以运行
$ cat filename.sql | sqlite3 movies.db > output.txt
将查询的输出重定向到名为 output.txt 的文本文件。(这对于检查查询返回了多少行很有用!)
如何测试 (How to Test)
虽然 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 列 and 10 行的表。 - 执行
9.sql会得到一张具有 2 列 and 36,219 行的表。 - 执行
10.sql会得到一张具有 1 列 and 4,675 行的表。 - 执行
11.sql会得到一张具有 1 列 and 5 行的表。 - 执行
12.sql会得到一张具有 1 列 and 4 行的表。 - 执行
13.sql会得到一张具有 1 列 and 550 行的表。
请注意,行数不包括仅显示列名的表头行。
如果你的查询返回的行数与预期输出略有不同,请务必正确处理重复项!对于要求提供姓名列表的查询,不应列出任何同一个人两次,但具有相同名字的两个不同的人应该各自列出。
正确性 (Correctness)
check50 cs50/problems/2026/x/movies
如何提交 (How to Submit)
在你的终端中,执行以下命令来提交你的工作,并回答出现的提示。
submit50 cs50/problems/2026/x/movies
致谢 (Acknowledgements)
信息由 IMDb (imdb.com) 提供。经许可使用。