สถานการณ์: คอลัมน์เก็บค่าหลายค่าคั่นด้วย Comma
ตาราง demo74: user_names VARCHAR(250) เก็บ "John Smith1,John Smith2,John Smith3"
ไวยากรณ์ LIKE พร้อม Wildcard
SELECT * FROM yourTable
WHERE yourColumn LIKE CONCAT('%', searchValue, '%')
ORDER BY id ASC
LIMIT limitValue;
ตัวอย่างข้อมูล
INSERT INTO demo74 (user_names) VALUES
('John Smith1,John Smith2,John Smith3'),
('John Smith1'),
('David Smith1'),
('John Smith1,John Smith2,John Smith3,John Smith4');
คำสั่งค้นหา "John Smith1"
SELECT * FROM demo74 WHERE user_names LIKE '%John Smith1%' ORDER BY user_id ASC LIMIT 100;
ผลลัพธ์ (3 แถว)
+---------+-------------------------------------------------+ | user_id | user_names | +---------+-------------------------------------------------+ | 1 | John Smith1,John Smith2,John Smith3 | | 2 | John Smith1 | | 4 | John Smith1,John Smith2,John Smith3,John Smith4 | +---------+-------------------------------------------------+
ปัญหาของ LIKE '%value%'
- False Positives: ค้นหา "John" จะเจอ "Johnson", "Johnathan"
- Full Table Scan: ไม่ใช้ INDEX ได้
- CSV Boundary: "John Smith1" match "John Smith10" (หากไม่มี Delimiter)
วิธีแก้: ใช้ Delimiter ใน LIKE
WHERE CONCAT(',', user_names, ',') LIKE '%,John Smith1,%'
วิธีที่ดีกว่า: FIND_IN_SET()
SELECT * FROM demo74
WHERE FIND_IN_SET('John Smith1', user_names) > 0;
- จัดการ CSV Boundary อัตโนมัติ
- เร็วกว่า LIKE (Internal Optimization)
- แต่: ต้องไม่มี Space หลัง Comma (ต้องเป็น 'A,B' ไม่ใช่ 'A, B')
แนวทางแก้รากฐาน: Normalization
แทน CSV ใน 1 คอลัมน์ ให้สร้างตารางความสัมพันธ์:
CREATE TABLE user_names (
user_id INT,
name VARCHAR(100),
PRIMARY KEY (user_id, name),
FOREIGN KEY (user_id) REFERENCES users(id)
);
Query แล้ว JOIN:
SELECT u.* FROM users u JOIN user_names un ON u.id = un.user_id WHERE un.name = 'John Smith1';
ประสิทธิภาพเปรียบเทียบ
| วิธี | ความเร็ว | ความแม่นยำ | ใช้ Index |
|---|---|---|---|
| LIKE '%val%' | ช้า | ต่ำ (False +) | ไม่ได้ |
| LIKE '%,val,%' | ช้า | ปานกลาง | ไม่ได้ |
| FIND_IN_SET | ปานกลาง | สูง (CSV) | ไม่ได้ |
| Normalized + JOIN | เร็ว | สูงสุด | ได้ ✅ |
| FULLTEXT INDEX | เร็ว | สูง (Text) | ได้ ✅ |
Spring Boot / Application Layer
ใน Application ให้ Parse CSV → List → ใช้ IN clause หรือ ANY (PostgreSQL) / MEMBER OF (Oracle) แทน