如何在 MySQL 中正确使用 CASE..WHEN

Posted

技术标签:

【中文标题】如何在 MySQL 中正确使用 CASE..WHEN【英文标题】:How do I use properly CASE..WHEN in MySQL 【发布时间】:2012-03-24 04:28:04 【问题描述】:

这是一个演示查询,注意它很简单,只获取base_price为0的地方, 而且,它仍然选择条件 3:

SELECT
   CASE course_enrollment_settings.base_price
    WHEN course_enrollment_settings.base_price = 0      THEN 1
    WHEN course_enrollment_settings.base_price<101      THEN 2
    WHEN course_enrollment_settings.base_price>100 AND   
                      course_enrollment_settings.base_price<201 THEN 3
        ELSE 6
   END AS 'calc_base_price',
   course_enrollment_settings.base_price
FROM
    course_enrollment_settings
WHERE course_enrollment_settings.base_price = 0

base_pricedecimal(8,0)

在我的数据库上运行它时,我得到:

3 0 3 0 3 0 3 0 3 0

【问题讨论】:

【参考方案1】:

立即删除CASE之后的course_enrollment_settings.base_price

SELECT
   CASE
    WHEN course_enrollment_settings.base_price = 0      THEN 1
    ...
    END

CASE 有两种不同的形式,详见manual。在这里,您需要第二种形式,因为您使用的是搜索条件

【讨论】:

如果您想按值排序,由于没有列别名,order by 子句会是什么样子?【参考方案2】:
CASE case_value
    WHEN when_value THEN statements
    [WHEN when_value THEN statements]
    ELSE statements
END 

或者:

CASE
WHEN <search_condition> THEN statements
[WHEN <search_condition> THEN statements] 
ELSE statements
END 

这里 CASE 是第二个场景中的表达式 search_condition 将评估,如果没有 search_condition 相等则执行 else

SELECT
   CASE course_enrollment_settings.base_price
    WHEN course_enrollment_settings.base_price = 0      THEN 1

应该是

SELECT
   CASE 
    WHEN course_enrollment_settings.base_price = 0      THEN 1

【讨论】:

括号是什么? [] @Shafizadeh 这些暗示您可以在第一个之后添加更多 when 语句。【参考方案3】:

CASE course_enrollment_settings.base_price这里写错了,应该是CASE

SELECT 
CASE 
WHEN course_enrollment_settings.base_price = 0      THEN 1 
WHEN course_enrollment_settings.base_price<101      THEN 2 
WHEN course_enrollment_settings.base_price>100 AND    
                  course_enrollment_settings.base_price<201 THEN 3 
    ELSE 6 
END AS 'calc_base_price', 
course_enrollment_settings.base_price 
FROM 
  course_enrollment_settings 
WHERE course_enrollment_settings.base_price = 0 

一些解释。您的原始查询将被执行为:

SELECT 
CASE 0
WHEN 0=0 THEN 1 -- condition evaluates to 1, then 0 (from CASE 0)compares to 1 - false
WHEN 0<1 THEN 2 -- condition evaluates to 1,then 0 (from CASE 0)compares to 1 - false
WHEN 0>100 and 0<201 THEN 3 -- evaluates to 0 ,then 0 (from CASE 0)compares to 0 - true
ELSE 6, ...

这就是为什么你总是得到 3

【讨论】:

“不需要”是不精确的。这是“你不应该拥有”。 @Lightness Races in Orbi:同意;我改了,加了一些解释 添加列别名 AS 'calc_base_price 时出现错误。我通过在整个 (CASE ... END) 周围添加括号来解决它【参考方案4】:
SELECT
   CASE 
    WHEN course_enrollment_settings.base_price = 0      THEN 1
    WHEN course_enrollment_settings.base_price>0 AND  
         course_enrollment_settings.base_price<=100     THEN 2
    WHEN course_enrollment_settings.base_price>100 AND   
         course_enrollment_settings.base_price<201      THEN 3
        ELSE 6
   END AS 'calc_base_price',
   course_enrollment_settings.base_price
FROM
    course_enrollment_settings
WHERE course_enrollment_settings.base_price = 0

【讨论】:

稍微改变了你的条件。添加 【参考方案5】:

有two variants of CASE,但你没有使用你认为的那个。

你在做什么

CASE case_value
    WHEN when_value THEN statement_list
    [WHEN when_value THEN statement_list] ...
    [ELSE statement_list]
END CASE

每个条件都大致等同于if (case_value == when_value)(伪代码)。

但是,您将整个条件设置为 when_value,导致类似:

if (case_value == (case_value > 100))

现在,(case_value &gt; 100) 的计算结果为 FALSE,并且是您这样做的唯一条件之一。所以,现在你有:

if (case_value == FALSE)

FALSE 转换为 0,通过生成的完整表达式 if (case_value == 0),您现在可以看到第三个条件触发的原因。

你应该做什么

删除第一个course_enrollment_settings,这样就没有case_value,这会让mysql知道你打算使用CASE的第二个变体:

CASE
    WHEN search_condition THEN statement_list
    [WHEN search_condition THEN statement_list] ...
    [ELSE statement_list]
END CASE

现在您可以提供完整的条件为search_condition

另外,请阅读文档以了解您使用的功能。

【讨论】:

我需要什么——这很清楚,我实际上可以根据自己的情况进行调整。【参考方案6】:

我认为部分原因是您在CASE 之后声明了您选择的值,然后使用WHEN x = y 语法,这是使用CASE 的两种不同方法的组合。它应该是

CASE X
  WHEN a THEN ...
  WHEN b THEN ...

CASE
  WHEN x = a THEN ...
  WHEN x = b THEN ...

【讨论】:

以上是关于如何在 MySQL 中正确使用 CASE..WHEN的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PHP 将非英文字符正确保存到 MySQL 数据库中?

#yyds干货盘点# MySQL性能优化:如何高效正确的使用索引

如何使用 JDBC 从 Mysql 中检索正确编码的数据

Mysql-如何正确的使用索引以及索引的原理

你如何正确地用 NULL 更新 mysql 字段?

如何在 RDS 上正确使用 Knex / Bookshelf 和 MySQL