ปัญหา: CASE WHEN กับ Expression ซับซ้อน
บางครั้ง CASE WHEN ไม่ทำงานตามที่คาด เพราะ:
- Operator precedence (ลำดับความสำคัญของตัวดำเนินการ)
- Charset/Collation mismatch
- NULL handling
- Data type mismatch
ตัวอย่างที่ทำงานถูกต้อง
CREATE TABLE demo58 (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(20),
last_name VARCHAR(20)
);
INSERT INTO demo58 (first_name, last_name) VALUES
('John', 'Doe'), ('David', 'Smith'), ('John', 'Brown'), ('David', 'Miller');
คำสั่ง CASE WHEN แบบ Expression (มีวงเล็บครอบ)
SELECT (
CASE
WHEN (first_name = "John") THEN 'Carol'
WHEN (last_name = "Smith") THEN 'Doe'
END
) AS RESULT
FROM demo58;
ผลลัพธ์
+--------+ | RESULT | +--------+ | Carol | | Doe | | Carol | | NULL | +--------+
คำอธิบายแถวต่อแถว
| แถว | first_name | last_name | เงื่อนไข 1 | เงื่อนไข 2 | ผลลัพธ์ |
|---|---|---|---|---|---|
| 1 | John | Doe | TRUE | - | Carol |
| 2 | David | Smith | FALSE | TRUE | Doe |
| 3 | John | Brown | TRUE | - | Carol |
| 4 | David | Miller | FALSE | FALSE | NULL (ไม่มี ELSE) |
จุดสำคัญ: วงเล็บครอบ Expression
-- ถูกต้อง: CASE เป็น expression คืนค่า SELECT (CASE WHEN ... END) AS col FROM ... -- ผิด: ขาดวงเล็บอาจทำให้ parser 混淆 (confused) ในบางบริบท SELECT CASE WHEN ... END AS col FROM ... -- ยังทำงานได้ใน SELECT ธรรมดา
แนะนำให้ใส่วงเล็บครอบ (CASE ... END) เสมอเมื่อใช้เป็น expression ใน SELECT list
รูปแบบ CASE WHEN ทั้งสองแบบ
1. Simple CASE (เปรียบเทียบค่า)
CASE column
WHEN value1 THEN result1
WHEN value2 THEN result2
ELSE default_result
END
2. Searched CASE (เงื่อนไข Boolean) — ใช้ในตัวอย่าง
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
ELSE default_result
END
Best Practices
- ใส่
ELSEเสมอ เพื่อป้องกัน NULL ที่ไม่คาดคิด - ใช้วงเล็บในเงื่อนไขซับซ้อน:
WHEN (a = 1 AND b = 2) THEN ... - ชนิดข้อมูล THEN ทุกข้อต้องเข้ากันได้ (MySQL จะหา common type)
- หลีกเลี่ยง CASE ใน WHERE clause (ใช้ AND/OR/IN แทนได้เร็วกว่า)
ตัวอย่างเพิ่มเติม: CASE ใน UPDATE
UPDATE demo58
SET first_name = CASE
WHEN first_name = 'John' THEN 'Jonathan'
WHEN first_name = 'David' THEN 'Dave'
ELSE first_name
END;