CASE WHEN 是 MySQL 流程控制函數的核心,支援簡單/搜索/嵌套三種形式,廣泛用於報表轉換、分桶統計、動態排序等場景。本文通過建表、插數、多維案例,系統講解三大用法及實戰技巧。
CREATE TABLE `lee` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` char(20) DEFAULT NULL,
`birthday` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO lee(name,birthday) VALUES ('sam','1990-01-01');
INSERT INTO lee(name,birthday) VALUES ('lee','1980-01-01');
INSERT INTO lee(name,birthday) VALUES ('john','1985-01-01');
SELECT name,
CASE
WHEN birthday < '1981' THEN 'old'
WHEN birthday > '1988' THEN 'young'
ELSE 'ok'
END AS age_group
FROM lee;
結果:lee→old、john→ok、sam→young。
注意:日期字面量建議加引號 '1981',或使用 YEAR(birthday) 避免隱式轉換歧義。
SELECT name,
CASE name
WHEN 'sam' THEN 'young'
WHEN 'lee' THEN 'handsome'
ELSE 'good'
END AS label
FROM lee;
等同於 CASE WHEN name='sam' THEN ...,但可讀性更高,適用於枚舉值映射。
SELECT name, birthday,
CASE
WHEN birthday > '1983' THEN 'young'
WHEN name = 'lee' THEN 'handsome'
ELSE 'just so so'
END AS complex_label
FROM lee;
CREATE TABLE penalties (
paymentno INT PRIMARY KEY,
payment_date DATE NOT NULL,
amount DECIMAL(7,2) NOT NULL
);
INSERT INTO penalties VALUES (1,'2008-01-01',3.45),(2,'2009-01-01',50.45),(3,'2008-07-01',80.45);
-- 分級標籤
SELECT payment_date, amount,
CASE
WHEN amount >= 0 AND amount < 40 THEN 'low'
WHEN amount >= 40 AND amount < 80 THEN 'moderate'
WHEN amount >= 80 THEN 'high'
ELSE 'null'
END AS level
FROM penalties;
-- 子查詢篩選 low 級別
SELECT * FROM (
SELECT paymentno, amount,
CASE
WHEN amount >= 0 AND amount < 40 THEN 'low'
WHEN amount >= 40 AND amount < 80 THEN 'moderate'
WHEN amount >= 80 THEN 'high'
ELSE 'incorrect'
END AS lvl
FROM penalties
) p WHERE p.lvl = 'low';
SELECT DISTINCT a.PatientID, a.PatientCode, a.PatientSex, a.MobileNo, a.HomePhoneNo,
a.UserAge, a.PatientName, a.PatientIDCard,
DATE_FORMAT(a.RegistDate,'%Y-%m-%d') AS RegistDate,
CASE
WHEN b.usedstartTime IS NOT NULL AND b.UsedEndTime IS NULL THEN '1' -- 使用中
WHEN b.usedstartTime IS NOT NULL AND b.UsedEndTime IS NOT NULL THEN '2' -- 已歸還
END AS usedState
FROM mets_v_patient_baseinfo a
LEFT JOIN mets_devices_used_history b ON a.patientid = b.PatientID
WHERE (SELECT IFNULL(IsDeleted,0) FROM userpublic_info WHERE UserID = a.PatientID) = 0
ORDER BY PatientID DESC LIMIT 0,15;
THEN 後表達式類型必須兼容,否則隱式轉換導致精度損失或報錯。WHEN col = NULL 永不匹配,需用 IS NULL。CASE 列不可直接用於索引查找,若頻繁篩選結果值,考慮物化列+索引。