mysql Case函数的使用

本文深入探讨SQL中的Case函数,包括简单Case函数和Case搜索函数的语法与用法,通过多个实例展示其在数据分组、条件更新、检查约束、数据一致性验证等方面的应用,以及如何在Case函数中嵌套使用合计函数。

Case函数写法

Case具有两种格式, 简单Case函数和Case搜索函数。

简单Case函数

例子:

CASE sex 
         WHEN '1' THEN '男' 
         WHEN '2' THEN '女' 
ELSE '其他' END 

语法结构:

CASE value
	WHEN [compare_value] THEN result
   [WHEN [compare_value] THEN result …]
[ELSE result] END

语义:
    将case后面的值value分别和每个when子句后面的值compare_value进行相等比较,一旦和某个when子句后面的值相等则返回相应的then子句后面的值result。如果和所有when子句后面的值都不相等,则返回else子句后面的值。没有else部分则返回null。
    value可以是字面量、表达式或者列名。
    CASE表达式的数据类型取决于跟在then或else后面的表达式的类型。这些类型必须相同(可尝试做隐式类型转换),否则出错。

Case搜索函数

例子

CASE WHEN sex = '1' THEN '男' 
     WHEN sex = '2' THEN '女' 
ELSE '其他' END 

语法结构:

CASE
	WHEN [condition] THEN result
   [WHEN [condition] THEN result …]
[ELSE result] END

语义:
    如果某个when子句后面的条件condition为true,则返回相应的when子句后面的值result。如果所有的when子句后面的条件condition都不为true,则返回else子句后面的值。没有else部分则返回null.

case函数可以嵌套。

区别

这两种方式,可以实现相同的功能。简单Case函数的写法相对比较简洁,但是和Case搜索函数相比,功能方面会有些限制,比如写判断式。

还有一个需要注意的问题,Case函数只返回第一个符合条件的值,剩下的Case部分将会被自动忽略。
比如说,下面这段SQL,你永远无法得到“第二类”这个结果

CASE WHEN col_1 IN ( 'a', 'b') THEN '第一类' 
     WHEN col_1 IN ('a')       THEN '第二类' 
ELSE'其他' END 

下面我们来看一下,使用Case函数都能做些什么事情。

用法举例

一、已知数据按照另外一种方式进行分组,分析

有如下数据:(为了看得更清楚,我并没有使用国家代码,而是直接用国家名作为Primary Key)

国家(country)人口(population)
中国600
美国100
加拿大100
英国200
法国300
日本250
德国200
墨西哥50
印度250

根据这个国家人口数据,统计亚洲和北美洲的人口数量。应该得到下面这个结果。

人口
亚洲1100
北美洲250
其他700

想要解决这个问题,你会怎么做?生成一个带有洲Code的View,是一个解决方法,但是这样很难动态的改变统计的方式。
如果使用Case函数,SQL代码如下:

SELECT  SUM(population), 
        CASE country 
                WHEN '中国'     THEN '亚洲' 
                WHEN '印度'     THEN '亚洲' 
                WHEN '日本'     THEN '亚洲' 
                WHEN '美国'     THEN '北美洲' 
                WHEN '加拿大'  THEN '北美洲' 
                WHEN '墨西哥'  THEN '北美洲' 
        ELSE '其他' END 
FROM    Table_A 
GROUP BY CASE country 
                WHEN '中国'     THEN '亚洲' 
                WHEN '印度'     THEN '亚洲' 
                WHEN '日本'     THEN '亚洲' 
                WHEN '美国'     THEN '北美洲' 
                WHEN '加拿大'  THEN '北美洲' 
                WHEN '墨西哥'  THEN '北美洲' 
        ELSE '其他' END; 

同样的,我们也可以用这个方法来判断工资的等级,并统计每一等级的人数。SQL代码如下:

SELECT 
        CASE WHEN salary <= 500 THEN '1' 
             WHEN salary > 500 AND salary <= 600  THEN '2' 
             WHEN salary > 600 AND salary <= 800  THEN '3' 
             WHEN salary > 800 AND salary <= 1000 THEN '4' 
        ELSE NULL END salary_class, 
        COUNT(*) 
FROM    Table_A 
GROUP BY 
        CASE WHEN salary <= 500 THEN '1' 
             WHEN salary > 500 AND salary <= 600  THEN '2' 
             WHEN salary > 600 AND salary <= 800  THEN '3' 
             WHEN salary > 800 AND salary <= 1000 THEN '4' 
        ELSE NULL END; 

二、用一个SQL语句完成不同条件的分组

有如下数据 :

国家(country)性别(sex)人口(population)
中国1340
中国2260
美国145
美国255
加拿大151
加拿大249
英国140
英国260

按照国家和性别进行分组,得出结果如下:

国家
中国340260
美国4555
加拿大5149
英国4060

普通情况下,用UNION也可以实现用一条语句进行查询。但是那样增加消耗(两个Select部分),而且SQL语句会比较长。
下面是一个是用Case函数来完成这个功能的例子

SELECT country, 
       SUM( CASE WHEN sex = '1' THEN 
                      population ELSE 0 END),  --男性人口 
       SUM( CASE WHEN sex = '2' THEN 
                      population ELSE 0 END)   --女性人口 
FROM  Table_A 
GROUP BY country; 

这样我们使用Select,完成对二维表的输出形式,充分显示了Case函数的强大。

三、在Check中使用Case函数

在Check中使用Case函数在很多情况下都是非常不错的解决方法。可能有很多人根本就不用Check,那么我建议你在看过下面的例子之后也尝试一下在SQL中使用Check。
下面我们来举个例子
公司A,这个公司有个规定,女职员的工资必须高于1000块。如果用Check和Case来表现的话,如下所示

CONSTRAINT check_salary CHECK 
           ( CASE WHEN sex = '2' 
                  THEN CASE WHEN salary > 1000 
                        THEN 1 ELSE 0 END 
                  ELSE 1 END = 1 ) 

如果单纯使用Check,如下所示

CONSTRAINT check_salary CHECK 
           ( sex = '2' AND salary > 1000 ) 

女职员的条件倒是符合了,男职员就无法输入了

四、根据条件有选择的UPDATE

例,有如下更新条件
工资5000以上的职员,工资减少10%
工资在2000到4600之间的职员,工资增加15%
很容易考虑的是选择执行两次UPDATE语句,如下所示

– 条件1

UPDATE Personnel 
SET salary = salary * 0.9 
WHERE salary >= 5000; 

– 条件2

UPDATE Personnel 
SET salary = salary * 1.15 
WHERE salary >= 2000 AND salary < 4600; 

但是事情没有想象得那么简单,假设有个人工资5000块。首先,按照条件1,工资减少10%,变成工资4500。接下来运行第二个SQL时候,因为这个人的工资是4500在2000到4600的范围之内, 需增加15%,最后这个人的工资结果是5175,不但没有减少,反而增加了。如果要是反过来执行,那么工资4600的人相反会变成减少工资。暂且不管这个规章是多么荒诞,如果想要一个SQL 语句实现这个功能的话,我们需要用到Case函数。代码如下:

UPDATE Personnel 
SET salary = CASE WHEN salary >= 5000 
             THEN salary * 0.9 
WHEN salary >= 2000 AND salary < 4600 
THEN salary * 1.15 
ELSE salary END;

这里要注意一点,最后一行的ELSE salary是必需的,要是没有这行,不符合这两个条件的人的工资将会被写成NUll,那可就大事不妙了。在Case函数中Else部分的默认值是NULL,这点是需要注意的地方。

这种方法还可以在很多地方使用,比如说变更主键这种累活。
一般情况下,要想把两条数据的Primary key,a和b交换,需要经过临时存储,拷贝,读回数据的三个过程,要是使用Case函数的话,一切都变得简单多了。

p_keycol_1col_2
a1张三
b2李四
c3王五

假设有如上数据,需要把主键a和b相互交换。用Case函数来实现的话,代码如下

UPDATE SomeTable 
SET p_key = CASE WHEN p_key = 'a' THEN 'b' 
				 WHEN p_key = 'b' THEN 'a' 
ELSE p_key END 
WHERE p_key IN ('a', 'b'); 

同样的也可以交换两个Unique key。需要注意的是,如果有需要交换主键的情况发生,多半是当初对这个表的设计进行得不够到位,建议检查表的设计是否妥当。

五、两个表数据是否一致的检查

Case函数不同于DECODE函数。在Case函数中,可以使用BETWEEN,LIKE,IS NULL,IN,EXISTS等等。比如说使用IN,EXISTS,可以进行子查询,从而实现更多的功能。
下面具个例子来说明,有两个表,tbl_A,tbl_B,两个表中都有keyCol列。现在我们对两个表进行比较,tbl_A中的keyCol列的数据如果在tbl_B的keyCol列的数据中可以找到, 返回结果’Matched’,如果没有找到,返回结果’Unmatched’。
要实现下面这个功能,可以使用下面两条语句
– 使用IN的时候

SELECT keyCol, 
CASE WHEN keyCol IN ( SELECT keyCol FROM tbl_B ) 
THEN 'Matched' 
ELSE 'Unmatched' END Label 
FROM tbl_A; 

– 使用EXISTS的时候

SELECT keyCol, 
CASE WHEN EXISTS ( SELECT * FROM tbl_B 
WHERE tbl_A.keyCol = tbl_B.keyCol ) 
THEN 'Matched' 
ELSE 'Unmatched' END Label 
FROM tbl_A; 

使用IN和EXISTS的结果是相同的。也可以使用NOT IN和NOT EXISTS,但是这个时候要注意NULL的情况。

六、在Case函数中使用合计函数

假设有下面一个表

学号(std_id)课程ID(class_id)课程名(class_name)主修flag(main_class_flg)
1001经济学Y
1002历史学N
2002历史学N
2003考古学Y
2004计算机N
3004计算机N
4005化学N
5006数学N

有的学生选择了同时修几门课程(100,200),也有的学生只选择了一门课程(300,400,500)。选修多门课程的学生,要选择一门课程作为主修,主修flag里面写入 Y。只选择一门课程的学生,主修flag为N(实际上要是写入Y的话,就没有下面的麻烦事了,为了举例子,还请多多包含)。
现在我们要按照下面两个条件对这个表进行查询 :

  1. 只选修一门课程的人,返回那门课程的ID
  2. 选修多门课程的人,返回所选的主课程ID

简单的想法就是,执行两条不同的SQL语句进行查询。
条件1
– 条件1:只选择了一门课程的学生

SELECT std_id, MAX(class_id) AS main_class 
FROM Studentclass 
GROUP BY std_id 
HAVING COUNT(*) = 1; 

执行结果1

STD_IDMAIN_class
3004
4005
5006

条件2
– 条件2:选择多门课程的学生

SELECT std_id, class_id AS main_class 
FROM Studentclass 
WHERE main_class_flg = 'Y' ; 

执行结果2

STD_IDMAIN_class
1001
2003

如果使用Case函数,我们只要一条SQL语句就可以解决问题,具体如下所示

SELECT  std_id, 
CASE WHEN COUNT(*) = 1  --只选择一门课程的学生的情况 
THEN MAX(class_id) 
ELSE MAX(CASE WHEN main_class_flg = 'Y' 
THEN class_id 
ELSE NULL END 
) 
END AS main_class 
FROM Studentclass 
GROUP BY std_id; 

运行结果

STD_IDMAIN_class
1001
2003
3004
4005
5006

通过在Case函数中嵌套Case函数,在合计函数中使用Case函数等方法,我们可以轻松的解决这个问题。使用Case函数给我们带来了更大的自由度。
最后提醒一下使用Case函数的新手注意不要犯下面的错误

CASE col_1 
WHEN 1     THEN 'Right' 
WHEN NULL  THEN 'Wrong' 
END 

在这个语句中When Null这一行总是返回unknown,所以永远不会出现Wrong的情况。因为这句可以替换成WHEN col_1 = NULL,这是一个错误的用法,这个时候我们应该选择用WHEN col_1 IS NULL

<think>首先,用户的问题是关于MySQL中的CASE函数使用方法和示例。用户提到了一些引用,这些引用提供了关于CASE函数的信息,包括语法和示例。我需要基于这些引用构建一个清晰、结构化的回答。 关键点: - 用户引用了多个来源,描述了MySQLCASE函数的两种形式:简单函数和搜索函数。 - 简单函数:`CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END` - 搜索函数:`CASE WHEN [expr] THEN [result1]…ELSE [default] END` - 示例包括在SELECT语句中使用CASE来根据条件返回不同的结果。 我的回答必须: 1. 使用中文回答。 2. 结构清晰,帮助用户逐步解决问题。 3. 确保回答真实可靠,基于提供的引用。 4. 在引用的段落末尾自然地添加引用标识,例如[^1]。 5. 生成相关问题。 6. 对于数学表达式,使用$...$或$$...$$格式,但在这个上下文中,可能不涉及数学,所以可能不需要。 回答结构: - 介绍CASE函数的基本概念。 - 解释两种语法形式:简单CASE函数和搜索CASE函数。 - 提供每个语法的详细说明和示例。 - 讨论使用场景,如WHERE子句中的应用。 - 最后,生成相关问题。 基于引用: - 引用[1]:描述了两种语法形式。 - 引用[2]:提到CASE在WHERE子句中的使用。 - 引用[3]:提供了一个实际的SQL查询示例。 - 引用[4]:给出了简单CASE函数的语法。 - 引用[5]:讨论了数据类型的要求。 我需要整合这些信息。 大纲: 1. **引言**:简要介绍MySQL CASE函数的作用。 2. **语法形式**: - 简单CASE函数。 - 搜索CASE函数。 3. **示例**: - 使用简单CASE函数的例子。 - 使用搜索CASE函数的例子。 - 在WHERE子句中使用CASE的例子。 4. **注意事项**:如数据类型兼容性。 5. **生成相关问题**:在最后添加相关问题。 确保自然添加引用标识: - 在描述引用内容时,在末尾添加[^n]。 例如: - "MySQLCASE函数有两种语法形式:简单函数和搜索函数[^1]。" - 等等。 生成相关问题: - 基于主题,如优化、性能、其他应用。 相关问题: 1. CASE函数在性能方面有什么考虑? 2. 如何在GROUP BY或聚合函数使用CASE? 3. CASE函数与其他条件函数如IF()的比较? 现在,构建回答。</think>### MySQL CASE函数使用方法和示例 MySQL的`CASE`函数是一种强大的条件表达式工具,允许在SQL查询中根据条件返回不同的值。它类似于编程语言中的`if-else`语句,常用于数据转换、分类和动态计算。基于您的引用,我将详细介绍其两种语法形式(简单函数和搜索函数),并提供清晰的示例。确保回答真实可靠,我整合了引用中的关键信息[^1][^2][^3][^4][^5]。 --- ### 1. CASE函数的语法形式 MySQL的`CASE`函数有两种主要语法形式,适用于不同场景: - **简单CASE函数**: 这种形式直接比较一个列或表达式与一组固定值,适合等值比较。语法如下: ```sql CASE input_expression WHEN when_expression1 THEN result_expression1 WHEN when_expression2 THEN result_expression2 ... ELSE else_result_expression END ``` 其中: - `input_expression` 是要比较的列或表达式。 - `when_expression` 是匹配值,必须与 `input_expression` 的数据类型兼容(例如,同为整数或字符串)[^5]。 - `result_expression` 是匹配时返回的结果。 - `ELSE` 是可选的,提供默认值;如果省略,未匹配时返回`NULL`[^4]。 - **搜索CASE函数**: 这种形式支持更复杂的条件(如不等式或逻辑组合),适用于非等值判断。语法如下: ```sql CASE WHEN condition1 THEN result_expression1 WHEN condition2 THEN result_expression2 ... ELSE else_result_expression END ``` 其中: - `condition` 是一个布尔表达式(例如 `score > 80`)。 - 其他部分与简单函数类似[^1][^2]。 两种形式都以`END`结束,且可以在`SELECT`、`WHERE`、`GROUP BY`等子句中使用[^2][^5]。 --- ### 2. CASE函数使用示例 以下示例基于真实场景,展示`CASE`函数在查询中的应用。假设我们有一个表`user_scores`,包含字段`user_id`、`score`(分数)和`subject`(科目)。 #### 示例1:简单CASE函数(用于分类) 在`SELECT`子句中,根据分数范围返回文本描述(如“优秀”、“及格”)。 ```sql SELECT subject, score, CASE score WHEN 90 THEN '优秀' WHEN 80 THEN '良好' WHEN 60 THEN '及格' ELSE '不及格' END AS result FROM user_scores WHERE user_id = '37391685121999872'; ``` - **解释**: - `input_expression` 是 `score` 列。 - 当`score`等于90时返回“优秀”,等于80时返回“良好”,以此类推。 - `ELSE`处理其他分数(如70分),返回“不及格”。 - **输出示例**: | subject | score | result | |---------|-------|----------| | Math | 90 | 优秀 | | English | 70 | 不及格 | 此示例基于引用[^3],但优化了条件逻辑以提高可读性。 #### 示例2:搜索CASE函数(用于动态计算) 在`SELECT`子句中,根据分数范围动态计算奖励积分。 ```sql SELECT subject, score, CASE WHEN score > 90 THEN score * 1.2 -- 优秀奖励20%积分 WHEN score > 80 THEN score * 1.1 -- 良好奖励10%积分 WHEN score > 60 THEN score -- 及格无奖励 ELSE 0 -- 不及格积分为0 END AS bonus_points FROM user_scores; ``` - **解释**: - 使用不等式条件(`score > 90`),适合搜索函数。 - 根据分数范围计算不同的`bonus_points`。 - 未指定`ELSE`时,默认返回`NULL`;这里显式设为0。 - **输出示例**: | subject | score | bonus_points | |---------|-------|-------------| | Math | 95 | 114.0 | | English | 75 | 75.0 | #### 示例3:在WHERE子句中使用CASE(用于过滤) 结合`WHERE`子句,动态过滤数据。例如,只查询分数在特定范围内的记录。 ```sql SELECT * FROM user_scores WHERE CASE WHEN subject = 'Math' THEN score > 80 WHEN subject = 'English' THEN score > 70 ELSE score > 60 END; ``` - **解释**: - 这里`CASE`返回布尔值(`TRUE`或`FALSE`),用于过滤行。 - 数学科目要求分数>80,英语>70,其他科目>60。 - 这在数据清洗或条件查询中非常有用[^2]。 --- ### 3. 注意事项 - **数据类型兼容性**:在简单CASE函数中,`input_expression`和`when_expression`必须数据类型一致或可隐式转换(例如,整数和浮点数兼容)[^5]。 - **性能优化**:`CASE`函数在大型表中可能影响性能;建议在索引列上使用简单函数,或避免嵌套复杂条件。 - **常见错误**:忘记`END`关键字或条件重叠(例如,多个`WHEN`条件可能同时匹配;MySQL按顺序评估,只返回第一个匹配结果)。 通过合理使用`CASE`函数,您可以简化查询逻辑,实现动态数据转换[^1][^3]。如果您有具体数据表结构,我可以提供更针对性的示例! --- ### 相关问题 1. CASE函数在WHERE子句中使用时,如何优化查询性能? 2. CASE函数与其他条件函数(如IF())相比,有什么优缺点? 3. 如何在GROUP BY聚合查询中使用CASE函数进行分类汇总? [^1]: MySQL case when 用法。MySQLcase when 的语法有两种:简单函数和搜索函数[^1]。 [^2]: mysql-函数CASE WHEN 语句使用说明。CASE可能在 SQL 中被误用最多的关键字之一,可以在WHERE子句中使用[^2]。 [^3]: mysqlcase的用户,示例代码展示了在SELECT子句中使用搜索函数进行分数分类[^3]。 [^4]: 有关mysqlCASE的sql语句用法,简单CASE函数的语法细节[^4]。 [^5]: MySQLCASE WHEN 语句使用说明,input_expression和when_expression的数据类型必须相同或可隐性转换[^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值