如何使用SQL系列 之 如何在SQL中使用CASE表达式

引言

编程语言通常以条件语句 为特征,它们是执行特定操作直到满足特定条件的命令。一个常见的条件语句是if, then, else语句,它通常遵循以下逻辑:

复制代码
if condition=true
	then action A
	else action B

这条语句的逻辑可以翻译成如下语言:"如果condition为真,那么perform action A。否则(else),执行动作B。"

CASE表达式是结构化查询语言(SQL)中的一个功能,它允许你对数据库查询应用类似的逻辑,并设置如何返回或显示结果集中值的条件。

在本教程中,你将学习如何使用CASE表达式,使用WHENTHENELSEEND关键字对数据设置条件。

前期准备

为了学习本指南,你需要一台运行某种使用SQL的关系数据库管理系统(RDBMS)的计算机。

注意:请注意,许多RDBMS使用它们自己独特的SQL实现。虽然本教程中概述的命令适用于大多数RDBMS,但如果你在MySQL以外的系统上测试它们,确切的语法或输出可能会有所不同。

你还需要一个装载了一些示例数据的数据库和表,可以在其中练习使用相关命令。

连接到MySQL并设置一个示例数据库

如果SQL数据库系统运行在远程服务器上,请从本地设备SSH到服务器:

shell 复制代码
ssh sammy@your_server_ip

然后打开MySQL服务器提示符,将==sammy==替换为你的MySQL用户账户的名称:

shell 复制代码
mysql -u sammy -p

创建一个名为caseDB的数据库:

sql 复制代码
CREATE DATABASE caseDB;

如果数据库成功创建,您将收到这样的输出:

shell 复制代码
OutputQuery OK, 1 row affected (0.01 sec)

要选择caseDB数据库,运行以下USE语句:

shell 复制代码
USE caseDB;
shell 复制代码
OutputDatabase changed

选择数据库后,在其中创建一个表。在本教程的示例中,我们将创建一个表,用于保存历史上最畅销的10个专辑的数据。这个表将包含以下6列:

  • music_id:显示int数据类型的值,并作为表的主键,这意味着这一列中的每个值都将作为其各自行的唯一标识符。
  • artist_name:使用varchar数据类型存储每个艺术家的名字,最多30个字符。
  • album_name:使用varchar数据类型,再一次最多30个字符每个专辑的名称。
  • release_date:使用 date数据类型跟踪每张专辑的发行日期,该数据类型使用YYYY-MM-DD日期格式。
  • genre_type:显示每个专辑的流派分类用的varchar数据类型最多25个字符。
  • copyes_sold:使用decimal数据类型存储以百万为单位售出的专辑拷贝总数。该列的精度为4,刻度为1,这意味着该列中的值可以有4位数字,其中一位位于小数点的右侧。

通过运行以下CREATE TABLE命令,创建一个名为top_albums的表,其中包含这些列:

sql 复制代码
CREATE TABLE top_albums (
music_id int, 
artist_name varchar(30),
album_name varchar(30), 
release_date DATE,
genre_type varchar(25),
copies_sold decimal(4,1),
PRIMARY KEY (music_id)
); 

接下来向空表中插入一些示例数据:

sql 复制代码
INSERT INTO top_albums
(music_id, artist_name, album_name, release_date, genre_type, copies_sold)
VALUES
(1, 'Michael Jackson', 'Thriller', '1982-11-30', 'Pop', 49.2),
(2, 'Eagles', 'Hotel California', '1976-12-08', 'Soft Rock', 31.5),
(3, 'Pink Floyd', 'The Dark Side of the Moon', '1973-03-01', 'Progressive Rock', 21.7),
(4, 'Shania Twain', 'Come On Over', '1997-11-04', 'Country', 29.6),
(5, 'AC/DC', 'Back in Black', '1980-07-25', 'Hard Rock', 29.5),
(6, 'Whitney Houston', 'The Bodyguard', '1992-11-25', 'R&B', 32.4),
(7, 'Fleetwood Mac', 'Rumours', '1977-02-04', 'Soft Rock', 27.9),
(8, 'Meat Loaf', 'Bat Out of Hell', '1977-10-11', 'Hard Rock', 21.7),
(9, 'Eagles', 'Their Greatest Hits 1971-1975', '1976-02-17', 'Country Rock', 41.2),
(10, 'Bee Gees', 'Saturday Night Fever', '1977-11-15', 'Disco', 21.6);
shell 复制代码
OutputQuery OK, 10 rows affected (0.01 sec)
Records: 10  Duplicates: 0  Warnings: 0

插入数据后,就可以开始在SQL中使用CASE表达式了。

理解CASE表达式的语法

CASE表达式允许你为数据设置条件,并使用类似于if-then语句的逻辑来搜索数据,比较值,并评估它们是否符合你设置的条件。下面是CASE表达式的通用语法示例:

CASE表达式语法

复制代码
. . .
CASE 
    WHEN condition_1 THEN outcome_1
    WHEN condition_2 THEN outcome_2
    WHEN condition_3 THEN outcome_3
    ELSE else_outcome
END 
. . .

根据你想为你的数据设置多少条件,你还需要在CASE表达式中包含以下关键字:

  • WHEN:这个关键字根据你设置的条件对表中的数据值进行计算和比较。WHEN与典型的if-then-else语句中的if类似。
  • THEN:如果某个值不满足条件,这个关键字会过滤你设置的每个条件。
  • ELSE:如果数据值不满足你在每个WHENTHEN语句后设置的任何条件,那么这个关键字可以用来指定它的最终分类条件。
  • END:为了成功运行CASE表达式并设置条件,你必须以END关键字结尾。

有了对CASE表达式结构和语法的理解,你就可以开始练习示例数据了。

使用CASE表达式

想象一下,你是一名DJ,正在为你古怪的卡罗尔阿姨的65岁生日庆祝活动准备曲目。你知道她的味道很难确定,所以你决定做一些研究十大畅销唱片的通知你的一些音乐的决定。

首先,通过运行SELECT*符号来查看你在top_albums表中编译的所有数据:

sql 复制代码
SELECT * FROM top_albums;
shell 复制代码
Output+----------+-----------------+-------------------------------+--------------+------------------+-------------+
| music_id | artist_name     | album_name                    | release_date | genre_type       | copies_sold |
+----------+-----------------+-------------------------------+--------------+------------------+-------------+
|        1 | Michael Jackson | Thriller                      | 1982-11-30   | Pop              |        49.2 |
|        2 | Eagles          | Hotel California              | 1976-12-08   | Soft Rock        |        31.5 |
|        3 | Pink Floyd      | The Dark Side of the Moon     | 1973-03-01   | Progressive Rock |        21.7 |
|        4 | Shania Twain    | Come On Over                  | 1997-11-04   | Country          |        29.6 |
|        5 | AC/DC           | Back in Black                 | 1980-07-25   | Hard Rock        |        29.5 |
|        6 | Whitney Houston | The Bodyguard                 | 1992-11-25   | R&B              |        32.4 |
|        7 | Fleetwood Mac   | Rumours                       | 1977-02-04   | Soft Rock        |        27.9 |
|        8 | Meat Loaf       | Bat Out of Hell               | 1977-10-11   | Hard Rock        |        21.7 |
|        9 | Eagles          | Their Greatest Hits 1971-1975 | 1976-02-17   | Country Rock     |        41.2 |
|       10 | Bee Gees        | Saturday Night Fever          | 1977-11-15   | Disco            |        21.6 |
+----------+-----------------+-------------------------------+--------------+------------------+-------------+
10 rows in set (0.00 sec)

自从卡罗尔阿姨出生于1957年,她年轻的时候就喜欢上了很多七八十年代的热门歌曲。你知道她是流行音乐、软摇滚和迪斯科的超级粉丝,所以你要把这些放在你的歌曲列表中最重要的位置。

你可以通过使用CASE表达式来实现这一点,通过查询genre_type列下的数据值,为那些特定类型设置条件"高优先级"。下面的查询执行了此操作,并为CASE表达式创建的结果列创建了一个别名,命名为priority。该查询还包括artist_namealbum_namerelease_date以获取更多上下文。不要忘记使用END关键字来完成你的CASE表达式:

sql 复制代码
SELECT artist_name, album_name, release_date,
CASE WHEN genre_type = 'Pop' THEN 'High Priority' 
WHEN genre_type = 'Soft Rock' THEN 'High Priority'
WHEN genre_type = 'Disco' THEN 'High Priority'
END AS priority
FROM top_albums;
shell 复制代码
Output+-----------------+-------------------------------+--------------+---------------+
| artist_name     | album_name                    | release_date | priority      |
+-----------------+-------------------------------+--------------+---------------+
| Michael Jackson | Thriller                      | 1982-11-30   | High Priority |
| Eagles          | Hotel California              | 1976-12-08   | High Priority |
| Pink Floyd      | The Dark Side of the Moon     | 1973-03-01   | NULL          |
| Shania Twain    | Come On Over                  | 1997-11-04   | NULL          |
| AC/DC           | Back in Black                 | 1980-07-25   | NULL          |
| Whitney Houston | The Bodyguard                 | 1992-11-25   | NULL          |
| Fleetwood Mac   | Rumours                       | 1977-02-04   | High Priority |
| Meat Loaf       | Bat Out of Hell               | 1977-10-11   | NULL          |
| Eagles          | Their Greatest Hits 1971-1975 | 1976-02-17   | NULL          |
| Bee Gees        | Saturday Night Fever          | 1977-11-15   | High Priority |
+-----------------+-------------------------------+--------------+---------------+
10 rows in set (0.00 sec)

即使这个输出反映了你为那些"高优先级"类型设置的条件,由于你省略了ELSE关键字,这将导致未知或缺失的数据值,即NULL值。如果你的数据值满足你在CASE表达式中设置的所有条件,ELSE关键字可能没有必要,但它对于任何剩余数据都是有用的,因此可以根据单个条件对其进行正确分类。

对于下一个查询,编写相同的CASE表达式,但这次使用ELSE关键字设置条件。在下面的例子中,ELSE参数将genre_type中任何非高优先级的数据值标记为"Maybe":

sql 复制代码
SELECT artist_name, album_name, release_date,
CASE WHEN genre_type = 'Pop' THEN 'High Priority' 
WHEN genre_type = 'Soft Rock' THEN 'High Priority'
WHEN genre_type = 'Disco' THEN 'High Priority'
ELSE 'Maybe'
END AS priority
FROM top_albums;
复制代码
[sceondary_label Output]
+-----------------+-------------------------------+--------------+---------------+
| artist_name     | album_name                    | release_date | priority      |
+-----------------+-------------------------------+--------------+---------------+
| Michael Jackson | Thriller                      | 1982-11-30   | High Priority |
| Eagles          | Hotel California              | 1976-12-08   | High Priority |
| Pink Floyd      | The Dark Side of the Moon     | 1973-03-01   | Maybe         |
| Shania Twain    | Come On Over                  | 1997-11-04   | Maybe         |
| AC/DC           | Back in Black                 | 1980-07-25   | Maybe         |
| Whitney Houston | The Bodyguard                 | 1992-11-25   | Maybe         |
| Fleetwood Mac   | Rumours                       | 1977-02-04   | High Priority |
| Meat Loaf       | Bat Out of Hell               | 1977-10-11   | Maybe         |
| Eagles          | Their Greatest Hits 1971-1975 | 1976-02-17   | Maybe         |
| Bee Gees        | Saturday Night Fever          | 1977-11-15   | High Priority |
+-----------------+-------------------------------+--------------+---------------+
10 rows in set (0.00 sec)

这个输出现在更能代表您为具有最高优先级和不具有最高优先级的专辑设置的条件。尽管这有助于排在前四名的专辑Thriller, Hotel California, RumoursSaturday Night Fever你相信在这张名单上需要更多的多样性。但你也得说服卡罗尔阿姨。

你决定做一个小实验,让卡罗尔阿姨拓宽她的音乐调色板,听剩下的专辑。你不提供专辑的任何上下文,而是指导她如实为它们打分,称它们"Mellow, "Fun"或 "Boring."。一旦她完成了,她会给你一份手写的分数清单。现在你有了设置查询条件所需的信息,如下所示:

sql 复制代码
SELECT artist_name, album_name, release_date,
CASE WHEN genre_type = 'Hard Rock' THEN 'Boring' 
WHEN genre_type = 'Country Rock' THEN 'Mellow'
WHEN genre_type = 'Progressive Rock' THEN 'Fun'
WHEN genre_type = 'Country' THEN 'Fun'
WHEN genre_type = 'R&B' THEN 'Boring'
ELSE 'High Priority' 
END AS score
FROM top_albums;
shell 复制代码
Output
+-----------------+-------------------------------+--------------+---------------+
| artist_name     | album_name                    | release_date | score         |
+-----------------+-------------------------------+--------------+---------------+
| Michael Jackson | Thriller                      | 1982-11-30   | High Priority |
| Eagles          | Hotel California              | 1976-12-08   | High Priority |
| Pink Floyd      | The Dark Side of the Moon     | 1973-03-01   | Fun           |
| Shania Twain    | Come On Over                  | 1997-11-04   | Fun           |
| AC/DC           | Back in Black                 | 1980-07-25   | Boring        |
| Whitney Houston | The Bodyguard                 | 1992-11-25   | Boring        |
| Fleetwood Mac   | Rumours                       | 1977-02-04   | High Priority |
| Meat Loaf       | Bat Out of Hell               | 1977-10-11   | Boring        |
| Eagles          | Their Greatest Hits 1971-1975 | 1976-02-17   | Mellow        |
| Bee Gees        | Saturday Night Fever          | 1977-11-15   | High Priority |
+-----------------+-------------------------------+--------------+---------------+
10 rows in set (0.00 sec)

根据这个输出,阿姨卡罗尔似乎开放的新声音,你会惊喜地看到她的分数为平克弗洛伊德。但你对她对AC/DC, Meat Loaf和Whitney Houston的优秀曲调不感兴趣有点失望。

如果你能向卡罗尔阿姨展示一些专辑在客观上比其他专辑更受欢迎,她可能会更灵活,所以你决定用一些数字来左右决定。事实上,这十张专辑之所以排名前十是因为它们在过去几十年里卖给了粉丝数百万张。因此,在下一个查询中,你将创建一个新的CASE表达式,它根据copyes_sold中到目前为止售出的专辑的数值数据来设置一个分数。

你将使用CASE表达式将销量至少3500万张的专辑设置为"best",销量2500万张的专辑设置为"great",销量2000万张的专辑设置为"good",销量低于3500万张的专辑设置为"ordinary",如下例所示:

sql 复制代码
SELECT artist_name, album_name, release_date, CASE WHEN copies_sold >35.0 THEN 'best'
WHEN copies_sold >25.0 THEN 'great'
WHEN copies_sold >20.0 THEN 'good'
ELSE 'mediocre' END AS score FROM top_albums;
shell 复制代码
Output+-----------------+-------------------------------+--------------+-------+
| artist_name     | album_name                    | release_date | score |
+-----------------+-------------------------------+--------------+-------+
| Michael Jackson | Thriller                      | 1982-11-30   | best  |
| Eagles          | Hotel California              | 1976-12-08   | great |
| Pink Floyd      | The Dark Side of the Moon     | 1973-03-01   | good  |
| Shania Twain    | Come On Over                  | 1997-11-04   | great |
| AC/DC           | Back in Black                 | 1980-07-25   | great |
| Whitney Houston | The Bodyguard                 | 1992-11-25   | great |
| Fleetwood Mac   | Rumours                       | 1977-02-04   | great |
| Meat Loaf       | Bat Out of Hell               | 1977-10-11   | good  |
| Eagles          | Their Greatest Hits 1971-1975 | 1976-02-17   | best  |
| Bee Gees        | Saturday Night Fever          | 1977-11-15   | good  |
+-----------------+-------------------------------+--------------+-------+
10 rows in set (0.00 sec)

基于这些输出,没有一张专辑被评为"mediocre",因为他们都卖出了2000多万张。然而,也有一些专辑从分数上脱颖而出。现在你可以为卡罗尔阿姨提供确凿的证据,证明他们演奏过AC/DC或惠特尼·休斯顿,因为他们的专辑销量超过2500万张,使他们成为最伟大的音乐作品。

现在你已经了解了如何使用CASE表达式为各种目的以及字符和数字数据值设置条件。此外,CASE如何使用if-then逻辑来比较这些值并根据您所需的条件生成响应。

总结

理解如何使用CAST表达式可以帮助你将数据范围缩小到你设置的任何条件。无论你是想为某些价值观设置不同的优先级,还是根据流行观点或数字的标准对它们进行评分,它都可以根据你的需求灵活设置。如果你想了解在结果集中操作数据值的其他方法,请查看我们关于CAST函数和连接表达式的指南。

相关推荐
DONG91319 分钟前
《三驾马车:MySQL、MongoDB、Redis对比与融合实战》
数据库·redis·sql·mysql·mongodb·database
程序边界44 分钟前
从 Oracle 到 KingbaseES:企业信创改造的“抄作业”模板,直接套用!
数据库·oracle
funfan05171 小时前
奇怪的“bug”--数据库的“隐式转换”行为
数据库·bug
Jasonakeke1 小时前
【重学MySQL】八十八、8.0版本核心新特性全解析
android·数据库·mysql
comeoffbest1 小时前
PostgreSQL 能存万物:从安装到高级功能实战
数据库·postgresql
时序数据说2 小时前
IoTDB如何解决海量数据存储难题?
大数据·数据库·物联网·时序数据库·iotdb
小楓12013 小时前
MySQL數據庫開發教學(二) 核心概念、重要指令
开发语言·数据库·mysql
花果山总钻风3 小时前
MySQL奔溃,InnoDB文件损坏修复记录
数据库·mysql·adb
TDengine (老段)4 小时前
TDengine IDMP 运维指南(管理策略)
大数据·数据库·物联网·ai·时序数据库·tdengine·涛思数据
Full Stack Developme5 小时前
PostgreSQL interval 转换为 int4 (整数)
数据库·postgresql