Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

MySQL FIND_IN_SET: ค้นหาตัวเลขในคอลัมน์ CSV

ฟังก์ชัน FIND_IN_SET()

FIND_IN_SET(needle, haystack)

  • needle: ค่าที่ต้องการค้นหา (String)
  • haystack: สตริง CSV (Comma-Separated)
  • คืนค่า: ตำแหน่ง 1-based (1,2,3...) หรือ 0 ถ้าไม่พบ

ตัวอย่าง: ตาราง demo73

CREATE TABLE demo73 (
    interest_id VARCHAR(100),
    interest_name VARCHAR(100)
);

INSERT INTO demo73 VALUES
('100,101,103,105', 'SSC'),
('105,103,1005,1003,104', 'Computer'),
('110,105,104,111', 'Novel');

ข้อมูล

+-----------------------+---------------+
| interest_id           | interest_name |
+-----------------------+---------------+
| 100,101,103,105       | SSC           |
| 105,103,1005,1003,104 | Computer      |
| 110,105,104,111       | Novel         |
+-----------------------+---------------+

คำสั่ง: หา Interest ที่มี 103

SELECT * FROM demo73
WHERE FIND_IN_SET('103', interest_id) > 0;

ผลลัพธ์ (2 แถว)

+-----------------------+---------------+
| interest_id           | interest_name |
+-----------------------+---------------+
| 100,101,103,105       | SSC           |
| 105,103,1005,1003,104 | Computer      |
+-----------------------+---------------+

จุดสำคัญ

  • ค้นหา '103' → เจอใน '100,101,103,105' และ '105,103,1005...'
  • ไม่ เจอใน '1005' หรือ '1003' เพราะ FIND_IN_SET จับคู่ ทั้งค่า (Exact match per element)
  • ต่างจาก LIKE '%103%' ที่จะเจอ 1003, 1005 ด้วย (False Positive)

ข้อจำกัด

ข้อจำกัดรายละเอียด
DelimiterComma (,) เท่านั้น — ไม่รองรับ ; | tab อื่นๆ
Space'100, 101' จะไม่ match '101' (ต้อง '100,101')
NULLFIND_IN_SET('103', NULL) → NULL (ไม่ใช่ 0)
Indexไม่ใช้ INDEX ได้ → Full Table Scan
Lengthhaystack ต้อง ≤ 512 bytes (เก่า) / 64KB (ใหม่)

กรณีมี Space: ใช้ REPLACE ก่อน

WHERE FIND_IN_SET('103', REPLACE(interest_id, ', ', ',')) > 0;

แนวทางแทนที่ (Best Practice)

1. Normalized Table (แนะนำ)

CREATE TABLE interests (
    id INT PRIMARY KEY,
    name VARCHAR(100)
);

CREATE TABLE entity_interests (
    entity_id INT,
    interest_id INT,
    PRIMARY KEY (entity_id, interest_id),
    FOREIGN KEY (interest_id) REFERENCES interests(id)
);

2. JSON Column (MySQL 5.7+)

ALTER TABLE demo73 ADD interests JSON;
UPDATE demo73 SET interests = JSON_ARRAY(100,101,103,105) WHERE interest_name = 'SSC';

SELECT * FROM demo73 WHERE JSON_CONTAINS(interests, '103');

3. Generated Column + Index (MySQL 5.7+)

ALTER TABLE demo73 
ADD COLUMN has_103 BOOLEAN AS (FIND_IN_SET('103', interest_id) > 0) STORED,
ADD INDEX idx_has_103 (has_103);