1.4 Blank vs Empty vs NULL 🔥
มี 3 สิ่งที่ “ดูว่าง” เหมือนกัน แต่คอมพิวเตอร์ถือว่าเป็นคนละเรื่อง — ถ้าคุณแยกไม่ออก คุณจะนับข้อมูลผิด กรองข้อมูลพลาด และ JOIN ล้มเหลวแบบเงียบๆ
3 แบบของ “ว่าง”
Section titled “3 แบบของ “ว่าง””ลองนึกภาพ กล่อง:
- NULL / Blank (ว่างจริงๆ) — กล่องไม่มีอยู่เลย หรือมีแต่ไม่เคยใส่อะไร → ความหมาย: “เราไม่รู้ค่า”
- Empty string
""— กล่องมีอยู่ มีป้ายชื่อ แต่ข้างในว่างเปล่า → ความหมาย: “เรารู้ว่ามันคือ — ไม่มีอะไร” - Zero
0— กล่องมีของอยู่ และของนั้นคือเลข 0 → ความหมาย: “มีค่า และค่านั้นคือศูนย์”
ตัวอย่างในชีวิตจริง
Section titled “ตัวอย่างในชีวิตจริง”| สถานการณ์ | ค่าที่ควรเก็บ | ทำไม |
|---|---|---|
| นักเรียนยังไม่กรอกเบอร์โทร | NULL | เราไม่รู้เบอร์ |
| นักเรียนกรอกเบอร์แล้วลบออก | "" (empty string) | เรารู้ว่าเขาเลือกจะไม่ให้เบอร์ |
| คะแนนสอบที่ยังไม่ตรวจ | NULL | ยังไม่มีค่า |
| คะแนนสอบที่ตรวจแล้วได้ 0 | 0 | มีค่า คือศูนย์คะแนน |
| นักเรียนไม่มี middle name | "" | มีคำตอบ: “ไม่มี” |
สร้างตารางนี้:
| A | B (คำอธิบาย) | |
|---|---|---|
| 1 | (เว้นว่าง) | Blank cell |
| 2 | ="" (พิมพ์สูตร) | Empty string |
| 3 | 0 | Zero |
ตรวจสอบ:
=ISBLANK(A1) → TRUE (ว่างจริง)=ISBLANK(A2) → FALSE (!) — มี empty string อยู่=ISBLANK(A3) → FALSE — มีค่า 0
=A1="" → TRUE=A2="" → TRUE=A3="" → FALSE — 0 ไม่ใช่ empty string
=LEN(A1) → 0=LEN(A2) → 0=LEN(A3) → 1 — "0" มีความยาว 1 ตัวอักษร
=COUNTBLANK(A1:A3) → 2 (!) — นับทั้ง blank และ empty string!ดักตรง: ISBLANK("") = FALSE แต่ COUNTBLANK("") = 1
นี่คือสาเหตุที่คนนับข้อมูลผิดบ่อยมาก!
ลองเพิ่ม:
=COUNTA(A1:A3) → 2 — นับเซลล์ที่มี "อะไรสักอย่าง" (A2 กับ A3)สังเกต: COUNTA นับ empty string ว่า “มีค่า” แต่ COUNTBLANK นับ empty string ว่า “ว่าง”
#include <stdio.h>#include <string.h>
int main() { // C ไม่มี NULL string โดยตรง — ใช้ pointer char *null_str = NULL; // pointer ชี้ไปไม่มีที่ไหน char empty[] = ""; // string ที่มีแค่ '\0' char zero[] = "0"; // string ที่มี '0' แล้วตามด้วย '\0'
// ตรวจสอบ if (null_str == NULL) printf("null_str: NULL (no memory allocated)\n");
printf("empty: \"%s\" (len=%zu)\n", empty, strlen(empty)); // "" (len=0)
printf("zero: \"%s\" (len=%zu)\n", zero, strlen(zero)); // "0" (len=1)
// อันตราย: ถ้าลืมเช็ค NULL แล้วใช้ strlen // strlen(null_str); // ← CRASH! Segmentation fault
// เปรียบเทียบ printf("empty == zero? %d\n", strcmp(empty, zero) == 0); // 0 (FALSE) — ไม่เท่ากัน
// ตัวเลข 0 int num_zero = 0; printf("num_zero: %d\n", num_zero); // 0 — มีค่า!
return 0;}Key insight: ใน C การใช้ NULL pointer โดยไม่เช็คก่อน = crash ทันที ไม่มีการ “เงียบๆ ผ่าน” เหมือน Sheets
import pandas as pdimport numpy as np
# Python มี "ว่าง" หลายแบบnone_val = None # Python's nullnan_val = np.nan # Not a Number (pandas ใช้เป็น missing value)pd_na = pd.NA # pandas' official missing value (ใหม่กว่า)empty_str = "" # Empty stringzero_val = 0 # Zero
# ตรวจสอบprint(none_val is None) # Trueprint(pd.isna(none_val)) # Trueprint(pd.isna(nan_val)) # Trueprint(pd.isna(pd_na)) # Trueprint(pd.isna(empty_str)) # False — empty string ไม่ใช่ NA!print(pd.isna(zero_val)) # False — 0 ไม่ใช่ NA!
# ลองใน DataFramedf = pd.DataFrame({ 'phone': [None, np.nan, pd.NA, '', '0812345678']})print(df)# phone# 0 None ← missing# 1 NaN ← missing# 2 <NA> ← missing# 3 ← empty string (ไม่ใช่ missing!)# 4 0812345678 ← มีค่า
print(df['phone'].isna())# 0 True# 1 True# 2 True# 3 False ← empty string ไม่ถือว่า missing!# 4 False
# นับ missing valuesprint(df['phone'].isna().sum()) # 3print((df['phone'] == '').sum()) # 1Key insight: pandas มี missing value ถึง 3 แบบ (None, NaN, pd.NA) — ทั้งหมดถือว่า “ไม่รู้ค่า” แต่ "" ไม่ใช่ missing
CREATE TABLE test_empty ( id INTEGER, phone VARCHAR(20));
INSERT INTO test_empty VALUES (1, NULL); -- ไม่รู้เบอร์INSERT INTO test_empty VALUES (2, ''); -- รู้ว่าว่างINSERT INTO test_empty VALUES (3, '0'); -- มีค่า
-- ตรวจสอบSELECT id, phone, phone IS NULL AS is_null, phone = '' AS is_empty, LENGTH(phone) AS lenFROM test_empty;ผลลัพธ์:
id | phone | is_null | is_empty | len1 | NULL | true | NULL | NULL2 | | false | true | 03 | 0 | false | false | 1สังเกต:
NULL = ''ให้ NULL ไม่ใช่ TRUE หรือ FALSE — เพราะ NULL เทียบกับอะไรก็ได้ NULLLENGTH(NULL)ก็ได้ NULL- ใช้
IS NULLไม่ใช่= NULLเสมอ!
-- กับดักยอดนิยมSELECT * FROM test_empty WHERE phone = NULL;-- ได้ 0 แถว! (ผิด)
SELECT * FROM test_empty WHERE phone IS NULL;-- ได้ 1 แถว (ถูก)
-- นับSELECT COUNT(*) AS total_rows, -- 3 COUNT(phone) AS non_null, -- 2 SUM(CASE WHEN phone IS NULL THEN 1 ELSE 0 END) AS null_count, -- 1 SUM(CASE WHEN phone = '' THEN 1 ELSE 0 END) AS empty_count; -- 1Key insight: COUNT(column) ข้าม NULL โดยอัตโนมัติ แต่ COUNT(*) นับทุกแถว — ผลต่างคือจำนวน NULL
เปรียบเทียบ 3 แบบของ “ว่าง”
Section titled “เปรียบเทียบ 3 แบบของ “ว่าง””| Blank / NULL | Empty string "" | Zero 0 | |
|---|---|---|---|
| Sheets | เซลล์ว่าง, ISBLANK=TRUE | ="", ISBLANK=FALSE | 0, ISBLANK=FALSE |
| Python | None, NaN, pd.NA | "" | 0 |
| SQL | NULL, ใช้ IS NULL | '', ใช้ = '' | 0 |
| C | NULL pointer | "" (แค่ \0) | 0 |
| ความหมาย | ไม่รู้ค่า | รู้ว่าว่าง | มีค่า = ศูนย์ |