条件表达式:CASE WHEN与IF

引言 在查询中经常需要根据不同条件返回不同结果。MySQL提供了CASE WHEN和IF等条件表达式来实现。 一、CASE WHEN 表达式 1.1 简单CASE表达式 -- 语法 CASE expression WHEN value1 THEN result1 WHEN value2 THEN result2 ELSE default_result END -- 示例:订单状态转换 SELECT order_id, CASE status WHEN 1 THEN '待支付' WHEN 2 THEN '已支付' WHEN 3 THEN '已发货' WHEN 4 THEN '已完成' ELSE '未知' END AS status_text FROM orders; 1.2 搜索CASE表达式(推荐) -- 语法 CASE WHEN condition1 THEN result1 WHEN condition2 THEN result2 ELSE default_result END -- 示例:价格分级 SELECT name, price, CASE WHEN price < 2000 THEN '低价' WHEN price BETWEEN 2000 AND 5000 THEN '中价' WHEN price > 5000 THEN '高价' ELSE '未知' END AS price_level FROM products; 1.3 嵌套CASE SELECT name, CASE WHEN stock = 0 THEN '缺货' WHEN stock > 0 THEN CASE WHEN stock < 10 THEN '库存紧张' WHEN stock < 50 THEN '库存正常' ELSE '库存充足' END END AS stock_status FROM products; 二、IF() 函数 2.1 基本用法 -- IF(condition, value_if_true, value_if_false) SELECT name, price, IF(price > 5000, '高价', '普通价') AS price_tag FROM products; -- 多条件判断(嵌套IF) SELECT name, IF(stock > 0, IF(stock > 50, '充足', '正常'), '缺货' ) AS stock_status FROM products; 2.2 IF vs CASE WHEN -- IF:适合简单的二元判断 SELECT IF(score >= 60, '及格', '不及格') FROM students; -- CASE WHEN:适合多条件判断 SELECT CASE WHEN score >= 90 THEN '优秀' WHEN score >= 80 THEN '良好' WHEN score >= 60 THEN '及格' ELSE '不及格' END AS grade FROM students; 三、IFNULL() / COALESCE() 3.1 IFNULL() - 处理NULL -- IFNULL(expr, default_value) SELECT name, IFNULL(phone, '未提供') AS phone FROM users; -- 计算时避免NULL SELECT name, price * IFNULL(discount, 1) AS final_price FROM products; 3.2 COALESCE() - 返回第一个非NULL值 -- COALESCE(value1, value2, value3, ...) SELECT name, COALESCE(mobile, phone, email, '无联系方式') AS contact FROM users; 四、NULLIF() - 返回NULL -- NULLIF(expr1, expr2):如果相等返回NULL,否则返回expr1 SELECT NULLIF(10, 10); -- NULL SELECT NULLIF(10, 20); -- 10 -- 避免除零错误 SELECT sales / NULLIF(days, 0) AS avg_daily_sales FROM stats; 五、实战案例 案例1:分组统计 -- 统计各价格区间的商品数 SELECT SUM(CASE WHEN price < 2000 THEN 1 ELSE 0 END) AS low_price_count, SUM(CASE WHEN price BETWEEN 2000 AND 5000 THEN 1 ELSE 0 END) AS mid_price_count, SUM(CASE WHEN price > 5000 THEN 1 ELSE 0 END) AS high_price_count FROM products; 案例2:数据透视 -- 按月统计各状态订单数 SELECT DATE_FORMAT(created_at, '%Y-%m') AS month, SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) AS completed_count, SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) AS pending_count, SUM(CASE WHEN status = 'cancelled' THEN 1 ELSE 0 END) AS cancelled_count FROM orders GROUP BY DATE_FORMAT(created_at, '%Y-%m'); 案例3:动态排序 -- 根据参数动态排序 SET @sort_field = 'price'; SELECT * FROM products ORDER BY CASE @sort_field WHEN 'price' THEN price WHEN 'sales' THEN sales WHEN 'stock' THEN stock END DESC; 案例4:数据清洗 -- 清洗性别数据 UPDATE users SET gender = CASE WHEN gender IN ('male', 'M', '男', '1') THEN '男' WHEN gender IN ('female', 'F', '女', '0') THEN '女' ELSE '未知' END; 案例5:行列转换 -- 将多行转为多列 SELECT user_id, MAX(CASE WHEN subject = '数学' THEN score END) AS math_score, MAX(CASE WHEN subject = '语文' THEN score END) AS chinese_score, MAX(CASE WHEN subject = '英语' THEN score END) AS english_score FROM scores GROUP BY user_id; 六、性能优化 6.1 索引失效 -- ❌ 差:在索引列上使用CASE,索引失效 SELECT * FROM products WHERE CASE WHEN category = '手机' THEN price > 3000 ELSE price > 5000 END; -- ✅ 好:拆分条件 SELECT * FROM products WHERE (category = '手机' AND price > 3000) OR (category != '手机' AND price > 5000); 6.2 避免重复计算 -- ❌ 差:CASE重复计算 SELECT CASE WHEN price * 0.8 > 5000 THEN '高价' ELSE '普通' END AS tag1, CASE WHEN price * 0.8 > 3000 THEN '贵' ELSE '便宜' END AS tag2 FROM products; -- ✅ 好:先计算再判断 SELECT CASE WHEN discount_price > 5000 THEN '高价' ELSE '普通' END AS tag1, CASE WHEN discount_price > 3000 THEN '贵' ELSE '便宜' END AS tag2 FROM ( SELECT *, price * 0.8 AS discount_price FROM products ) t; 七、总结 核心要点 CASE WHEN:多条件判断,功能强大 简单CASE:匹配固定值 搜索CASE:复杂条件判断 IF():二元判断,简洁易读 IFNULL() / COALESCE():处理NULL值 NULLIF():避免除零错误 性能:避免在索引列上使用条件表达式 记忆口诀 条件表达式两大将,CASE WHEN IF各擅长, CASE多条件分级判,IF二元选择强。 IFNULL处理空值好,COALESCE多值找, NULLIF避免除零错,实战案例记心上。 本文字数:约2,600字 难度等级:⭐⭐(SQL进阶)

2025-11-20 · maneng

如约数科科技工作室

浙ICP备2025203501号

👀 本站总访问量 ...| 👤 访客数 ...| 📅 今日访问 ...