sql中case when的基本语法_mysql条件表达式说明

来源:这里教程网 时间:2026-02-28 20:39:13 作者:

CASE WHEN 在 MySQL 中怎么写才不会报错

MySQL 的

CASE WHEN
有两种写法:简单 CASE 和搜索 CASE。绝大多数报错(比如
ERROR 1064
)是因为混用或漏写关键子句。必须明确:没有
END
必报错;
ELSE
可省略,但省略后默认返回
NULL
,容易引发后续空值逻辑问题。

常见错误现象:

CASE column WHEN value THEN ...
却对
value
做表达式判断(如
WHEN column > 10
),这属于语法越界——简单 CASE 只支持等值比较,范围/逻辑判断必须用搜索 CASE。

简单 CASE:适用于列与常量的精确匹配,格式为
CASE column WHEN val1 THEN ... WHEN val2 THEN ... ELSE ... END
搜索 CASE:更常用,支持任意布尔表达式,格式为
CASE WHEN condition1 THEN ... WHEN condition2 THEN ... ELSE ... END
所有
THEN
后的表达式应尽量保持相同数据类型,否则 MySQL 会隐式转换,可能触发截断或精度丢失(例如混合返回
INT
VARCHAR

WHERE 里能用 CASE WHEN 吗?为什么经常不生效

不能直接在

WHERE
子句中用
CASE WHEN
做条件过滤主体——它不是布尔表达式生成器,而是值返回器。你写
WHERE CASE WHEN x>0 THEN 1 ELSE 0 END = 1
虽然语法合法,但可读性差、无法走索引,且掩盖了本可用原生逻辑表达的意图。

真正该用

CASE WHEN
的地方是:需要按条件动态计算字段值(
SELECT
)、分组依据(
GROUP BY
)、排序权重(
ORDER BY
)。在
WHERE
中,优先用原生布尔逻辑:
x > 0 AND y IS NOT NULL
,而不是套一层
CASE

例外场景:当需要复用复杂判断逻辑多次时,可先在
SELECT
或子查询中用
CASE
计算出标志位,再在外部
WHERE
过滤该别名(注意:不能在同级
WHERE
直接引用
SELECT
中的别名)
HAVING
中允许使用
CASE
,但仅限于已聚合后的结果再分类筛选

NULL 值在 CASE WHEN 中的坑怎么避

CASE WHEN
NULL
的处理非常严格:所有
= NULL
判断恒为
UNKNOWN
,即不会命中任何
WHEN
分支。这是 SQL 三值逻辑决定的,和编程语言中的
null == null
完全不同。

正确写法必须用

IS NULL
IS NOT NULL
显式判断。如果业务逻辑本意是“把空和零都归为一类”,也不能写成
WHEN col = 0 OR col = NULL
——后者第二部分永远不成立。

SELECT 
  id,
  CASE 
    WHEN status IS NULL THEN 'unknown'
    WHEN status = 0 THEN 'inactive'
    WHEN status = 1 THEN 'active'
    ELSE 'other'
  END AS status_label
FROM users;
不要依赖
ELSE
捕获
NULL
:如果
status
NULL
,且你没写
WHEN ... IS NULL
,它会掉进
ELSE
,但你未必意识到这是
NULL
导致的
函数如
COALESCE()
IFNULL()
更适合做空值兜底,
CASE
更适合多分支逻辑分流

性能影响:CASE WHEN 会让查询变慢吗

单个

CASE WHEN
分支本身开销极小,几乎可忽略。真正影响性能的是:分支内嵌套复杂子查询、调用非确定性函数(如
NOW()
RAND()
)、或在
JOIN
条件/索引字段上使用导致无法命中索引。

尤其注意:如果在

ORDER BY
GROUP BY
中用
CASE
表达式,MySQL 通常无法利用原有索引,会强制 filesort 或临时表——此时应考虑提前在应用层或物化视图中固化分类字段。

避免在
CASE
WHEN
条件中写
SELECT COUNT(*) FROM ...
这类子查询,每行都会执行一次
若分支逻辑固定且高频,建议建生成列(Generated Column)并加索引,比运行时计算更高效 EXPLAIN 结果中看到
Using filesort
Using temporary
,要回头检查
CASE
是否出现在排序/分组位置
实际用得多的从来不是语法本身,而是什么时候不该用它——比如本可以用
IF()
简化单条件,或本该拆成多个布尔字段却硬塞进一个
CASE

相关推荐