跳至主要内容

PostgreSQL 中的 CASE 语句

在本教程中,您将学习如何使用 PostgreSQL 的 CASE 条件表达式来编写条件查询。
· 7分钟 阅读

使用 AI 探索

条件表达式是任何编程范式中最基础的元素之一。常见的条件表达式包括 if-else 代码块和 switch 分支。在 PostgreSQL 中,您可以使用与 if-else 十分类似的 WHEN-THEN CASE 来构造条件表达式。本文将带您逐步掌握。

在编写条件查询之前,请先在本地搭建一个 PostgreSQL 数据库。您将在本教程的第一部分完成这一操作。

注意:为顺利跟进本教程,您需要具备 SQL 与 PostgreSQL 的基础知识。可参考以下资源进行复习:

在本地搭建 PostgreSQL 数据库

搭建数据库可参考这篇文章。成功恢复备份后,您应能在数据库中看到以下数据表:

  • countries
  • route_table
  • station_table
  • train_table

不过,本教程只使用 countries 表。您可自由探索备份中提供的其他表,或创建自己的数据库和数据表。如果您已恢复数据库备份,现在应当已有一个包含全球各国信息的数据表。下面我们简要浏览一下 countries 表。

简要探索 countries 表

恢复数据库后,您可以在 PostgreSQL 默认安装附带的 pgAdmin 界面中查看数据表。运行一条简单的 SELECT 语句,您即可了解表的列、数据类型以及包含的行:

database

该表包含来自世界各地区共 206 个国家/地区的详细信息。具体有多少个地区?下面这条查询能回答这个问题。

SELECT COUNT(DISTINCT(region)) from countries;

结果显示,该表覆盖了 23 个不同地区,例如西欧、波利尼西亚、中东等。您可以带着自己的小问题探索这张表,沿途或许还能发现有趣的事实。现在我们来了解一下基本的 PostgreSQL CASE 结构。

PostgreSQL CASE 简介

下面是带有 WHEN-THEN 结构的 PostgreSQL CASE 的一般形式:

CASE
     WHEN condition_1  THEN result_1
     WHEN condition_2  THEN result_2
     ...
     ELSE  result_n
END

在 PostgreSQL 中构造 CASE 时,请牢记以下要点:

  • 每个条件都是布尔表达式,依据其结果选择返回值。如果所有与 WHEN 对应的表达式都评估为 False,则显示 ELSE 部分对应的结果。若未指定 ELSE 部分,查询将返回 null。

  • 条件通常应用于您所操作表中存在的一列。类似上述的条件查询结构通常与 SELECT 语句一起使用。请注意:在指定布尔表达式的列(于 CASE 中)必须出现在查询的 SELECT 语句中。但当您将 CASE 与 where 子句配合使用时,则不受此限制(稍后详述)。

  • 结果的数据类型必须一致。不能在 result_1 返回 string,而在 result_2 返回 integer,等等。

下面通过一些示例来实践。

编写 PostgreSQL CASE

先从简单的开始。现在我们编写一个 CASE,按国家的独立年份进行分组。独立年份记录在 indep_year 列中。假设您需要遵循三个独立年份分组。我们将创建以下三组:

  • 1900 年之前(indep_year < 1900)
  • 1900 至 1930 年(含)(indep_year <= 1930)
  • 1930 年之后(indep_year > 1930)

查询的最终结果应包含以下列:

  • name(国家名称)
  • continent(所属洲)
  • indep_year
  • 以及您将创建的独立年份分组列。我们将其命名为 indep_year_group。

现在来编写查询:

SELECT name, continent, indep_year,
    CASE WHEN indep_year < 1900 THEN 'before 1900'
         WHEN indep_year <= 1930 THEN 'between 1900 and 1930'
         ELSE 'after 1930' END
         AS indep_year_group
FROM countries
ORDER BY indep_year_group;

(该查询灵感来自 DataCamp 的 Joining Data in SQL 课程。)

执行查询后,您会看到如巴勒斯坦、波多黎各等多个国家/地区在表中没有提供独立年份,因此被归入 between 1900 and 1930 分组。

PostgreSQL 的 CASE 可以包含多个条件。表中有少数记录的国家名与首都名相同。您可以把这一点加入前面的 CASE 中:

SELECT name, continent, indep_year,
    CASE WHEN (indep_year < 1900) AND (countries.name = countries.capital) THEN 'before 1900 and capital same'
         WHEN indep_year <= 1930 AND (countries.name = countries.capital) THEN 'between 1900 and 1930 and capital same'
         ELSE 'after 1930_and_no_same_capital' END
         AS indep_year_group
FROM countries
ORDER BY indep_year_group;

CASE 的另一个有趣之处在于它可以与 SUM() 等聚合函数配合使用。若要在聚合函数 SUM() 中使用 CASE,更适合换一张表来演示。我们创建一张名为 student_grades 的简单表,包含以下列及数据类型:

  • student_name(字符串)
  • student_stream(字符串)
  • student_grade(字符)

使用以下查询创建该表:

CREATE TABLE student_grades
(student_name character varying,
student_stream character varying,
student_grade character);

现在往表中插入一些记录。您可以使用若干条 INSERT 语句。假设插入后,student_grades 表包含以下记录:

table

接下来,编写一个 CASE 来统计属于特定成绩分组的学生数量。如下所示,根据表中的记录存在 A、B、C 三个不同的成绩。条件查询应返回类似下图的输出:

table

对应查询如下:

SELECT
 SUM (
 CASE
 WHEN student_grade = 'A' THEN
 1
 ELSE
 0
 END
 ) AS "High Scoring",
 SUM (
 CASE
 WHEN student_grade = 'B' THEN
 1
 ELSE
 0
 END
 ) AS "Mid Scoring",
 SUM (
 CASE
 WHEN student_grade = 'C' THEN
 1
 ELSE
 0
 END
 ) AS "Low Scoring"
FROM
 student_grades;

这就是将 CASE 与聚合函数配合使用,从而挖掘数据有趣结论的方式。

结语与延伸阅读

本教程到此结束。您已学习如何将类似 if-then 的条件逻辑融入 SQL 查询,以产出有价值的报表。我们通过多个示例巩固了这一技能。若想挑战更高难度的练习,推荐学习以下 DataCamp 的 SQL 课程:

欢迎在评论区提出您对本教程的疑问。

主题