สถานการณ์
คอลัมน์ isMarried TINYINT เก็บค่า: 1 (Married), 0 (Single), NULL (Unknown) ต้องการดึงแถวที่ ไม่ใช่ 1 (คือ 0 หรือ NULL)
วิธีแก้: ใช้ <> 1 OR IS NULL
WHERE isMarried <> 1 OR isMarried IS NULL
ตัวอย่างการใช้งาน
1. สร้างตาราง
mysql> CREATE TABLE DemoTable (
-> EmployeeId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> EmployeeName VARCHAR(20),
-> isMarried TINYINT
-> );
Query OK, 0 rows affected (0.83 sec)
2. เพิ่มข้อมูล
mysql> INSERT INTO DemoTable(EmployeeName, isMarried) VALUES('Chris', NULL);
Query OK, 1 row affected (0.76 sec)
mysql> INSERT INTO DemoTable(EmployeeName, isMarried) VALUES('David', 1);
Query OK, 1 row affected (0.35 sec)
mysql> INSERT INTO DemoTable(EmployeeName, isMarried) VALUES('Mike', 0);
Query OK, 1 row affected (0.69 sec)
mysql> INSERT INTO DemoTable(EmployeeName, isMarried) VALUES('Sam', NULL);
Query OK, 1 row affected (0.13 sec)
mysql> INSERT INTO DemoTable(EmployeeName, isMarried) VALUES('Bob', 0);
Query OK, 1 row affected (0.10 sec)
3. แสดงข้อมูลทั้งหมด
mysql> SELECT * FROM DemoTable;
ผลลัพธ์:
+------------+--------------+-----------+ | EmployeeId | EmployeeName | isMarried | +------------+--------------+-----------+ | 1 | Chris | NULL | | 2 | David | 1 | | 3 | Mike | 0 | | 4 | Sam | NULL | | 5 | Bob | 0 | +------------+--------------+-----------+ 5 rows in set (0.00 sec)
4. Query: isMarried <> 1 OR IS NULL
mysql> SELECT * FROM DemoTable WHERE isMarried <> 1 OR isMarried IS NULL;
ผลลัพธ์ (ไม่อาจารย์ David ที่ค่า 1):
+------------+--------------+-----------+ | EmployeeId | EmployeeName | isMarried | +------------+--------------+-----------+ | 1 | Chris | NULL | | 3 | Mike | 0 | | 4 | Sam | NULL | | 5 | Bob | 0 | +------------+--------------+-----------+ 4 rows in set (0.00 sec)
ทำไมต้อง OR IS NULL?
ใน SQL: NULL <> 1 คืนค่า UNKNOWN (ไม่ใช่ TRUE) ไม่ใช่ TRUE ดังนั้นแถวที่ isMarried = NULL จะไม่ถูก Select ด้วย <> 1 เพียงอย่างเดียว
Truth Table
| isMarried | <> 1 | IS NULL | OR Result |
|---|---|---|---|
| 1 | FALSE | FALSE | FALSE (Excluded) |
| 0 | TRUE | FALSE | TRUE (Included) |
| NULL | UNKNOWN | TRUE | TRUE (Included) |
วิธีเขียนแบบอื่น
1. ใช้ NOT IN (ไม่รองรับ NULL)
WHERE isMarried NOT IN (1) -- NULL จะไม่ถูก Select!
2. ใช้ COALESCE
WHERE COALESCE(isMarried, 0) <> 1
3. ใช้ NOT ( = 1 )
WHERE NOT (isMarried = 1) -- NULL = 1 → UNKNOWN → NOT UNKNOWN = UNKNOWN → Excluded!
4. ใช้ CASE WHEN (Explicit)
WHERE CASE WHEN isMarried = 1 THEN 0 ELSE 1 END = 1
Best Practice สำหรับ Boolean/TINYINT Column
- กำหนด
NOT NULL DEFAULT 0หากเป็นไปได้ (ลดความซับซ้อนของ NULL) - ใช้
IS TRUE,IS FALSE,IS NULL(MySQL Specific) WHERE isMarried IS NOT TRUE≡WHERE isMarried <> 1 OR isMarried IS NULL
กรณีการใช้งานจริง
- Soft Delete:
deleted TINYINT DEFAULT 0→ WHERE deleted IS NOT TRUE - Feature Flag:
enabled TINYINT→ WHERE enabled IS NOT TRUE (Disabled + Unknown) - Status: 1=Active, 0=Inactive, NULL=Pending → WHERE status IS NOT TRUE