悠悠楠杉
SQLCASEWHEN表达式:从基础到高阶的实战用法解析
一、为什么说CASE WHEN是SQL中最灵活的条件表达式?
在数据处理过程中,我们经常遇到这样的需求:当满足A条件时返回X结果,满足B条件时返回Y结果。与其他编程语言的if-else逻辑不同,SQL通过CASE WHEN语句实现条件分支。这种表达式不仅支持简单的值匹配,还能实现:
- 动态列生成
- 数据标准化
- 分段统计
- 多条件复合判断
二、基础用法:标准的条件分支结构
sql
SELECT
product_name,
CASE
WHEN price > 1000 THEN '高端'
WHEN price > 500 THEN '中端'
ELSE '平价'
END AS price_segment
FROM products;
这是最常见的等值判断形式,需要注意:
1. WHEN子句按书写顺序依次执行
2. 第一个满足条件的WHEN会终止后续判断
3. ELSE子句可省略(默认返回NULL)
三、实战进阶:7种典型业务场景解析
3.1 动态数据分桶(数据离散化)
做用户分层分析时,我们常需要将连续值转换为区间:
sql
SELECT
user_id,
CASE
WHEN age BETWEEN 18 AND 24 THEN '18-24'
WHEN age BETWEEN 25 AND 30 THEN '25-30'
WHEN age > 30 THEN '30+'
ELSE '未知'
END AS age_group
FROM users;
3.2 多列条件组合判断
电商订单状态判断示例:
sql
SELECT
order_id,
CASE
WHEN pay_status = 0 AND create_time < NOW() - INTERVAL '30m' THEN '待支付超时'
WHEN refund_flag = 1 THEN '已退款'
WHEN delivery_time IS NULL THEN '待发货'
ELSE '已完成'
END AS order_status
FROM orders;
3.3 行列转换(行转列)
将季度销售数据转为横向展示:
sql
SELECT
product_id,
SUM(CASE WHEN quarter = 'Q1' THEN amount ELSE 0 END) AS Q1_sales,
SUM(CASE WHEN quarter = 'Q2' THEN amount ELSE 0 END) AS Q2_sales
FROM sales
GROUP BY product_id;
3.4 数据清洗与标准化
统一用户手机号格式:
sql
UPDATE users
SET phone = CASE
WHEN phone LIKE '86%' THEN SUBSTRING(phone, 3)
WHEN phone LIKE '+86%' THEN SUBSTRING(phone, 4)
ELSE phone
END;
3.5 在聚合函数中条件计数
统计不同状态订单数:
sql
SELECT
COUNT(*) AS total_orders,
SUM(CASE WHEN status = 'paid' THEN 1 ELSE 0 END) AS paid_count,
SUM(CASE WHEN status = 'shipped' THEN 1 ELSE 0 END) AS shipped_count
FROM orders;
3.6 与窗口函数结合使用
计算各品类下的价格排名分档:
sql
SELECT
product_id,
category,
price,
CASE
WHEN PERCENT_RANK() OVER(PARTITION BY category ORDER BY price) > 0.9 THEN 'TOP10%'
WHEN PERCENT_RANK() OVER(PARTITION BY category ORDER BY price) > 0.7 THEN 'MID30%'
ELSE 'BOTTOM60%'
END AS price_tier
FROM products;
3.7 递归条件判断(嵌套CASE)
复杂的会员等级计算逻辑:
sql
SELECT
user_id,
CASE
WHEN total_consumption > 10000 THEN
CASE
WHEN recent_order_count > 10 THEN '钻石VIP'
ELSE '黄金VIP'
END
WHEN total_consumption > 5000 THEN '白银VIP'
ELSE '普通会员'
END AS member_level
FROM user_stats;
四、性能优化与避坑指南
索引失效警告:在WHERE条件中使用CASE WHEN会导致索引失效sql
-- 错误示例(无法使用price索引):
SELECT * FROM products
WHERE CASE WHEN type = '电子' THEN price*0.9 ELSE price END > 1000;-- 应改写为:
SELECT * FROM products
WHERE (type = '电子' AND price*0.9 > 1000)
OR (type != '电子' AND price > 1000);NULL处理技巧:使用COALESCE避免意外NULL值
sql SELECT CASE WHEN score IS NOT NULL THEN CASE WHEN score > 90 THEN 'A' ELSE 'B' END ELSE '未评分' END AS grade FROM exams;
保持类型一致:所有THEN返回值的类型应该相同,避免隐式转换
五、不同数据库的语法差异
| 特性 | MySQL | PostgreSQL | SQL Server |
|---------------|-------|------------|------------|
| 简单CASE表达式 | 支持 | 支持 | 支持 |
| IIF函数 | 8.0+ | 不支持 | 支持 |
| 布尔类型判断 | 特殊 | 标准 | 标准 |
特殊说明:MySQL中TRUE=1/FALSE=0,建议显式写成WHEN flag = 1
结语
思考题:如何用单个CASE WHEN实现RGB颜色值到十六进制编码的转换?(提示:使用嵌套子查询和字符串函数)