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

MySQL SELECT WHERE IN List String: ใช้ FIND_IN_SET

สถานการณ์: คอลัมน์เก็บรายชื่อคั่น Comma

คอลัมน์ username VARCHAR(200) เก็บ "John,Chris,David"

ฟังก์ชัน FIND_IN_SET()

FIND_IN_SET(needle, haystack)
-- คืนตำแหน่ง (1-based) หรือ 0 ถ้าไม่พบ

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

CREATE TABLE demo81 (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(200)
);

INSERT INTO demo81 (username) VALUES
('John,Chris,David'), ('Mike,Sam'), ('Chris,Bob,Sam'), ('Mike,John,Chris');

ข้อมูล

+----+------------------+
| id | username         |
+----+------------------+
| 1  | John,Chris,David |
| 2  | Mike,Sam         |
| 3  | Chris,Bob,Sam    |
| 4  | Mike,John,Chris  |
+----+------------------+

คำสั่ง: หาแถวที่มี 'Chris'

SELECT * FROM demo81
WHERE FIND_IN_SET('Chris', username) > 0;

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

+----+------------------+
| id | username         |
+----+------------------+
| 1  | John,Chris,David |
| 3  | Chris,Bob,Sam    |
| 4  | Mike,John,Chris  |
+----+------------------+

ทำไมไม่ใช้ LIKE?

QueryMatch 'Chris'Match 'Chris1' (False +)
LIKE '%Chris%'✅❌ Match
FIND_IN_SET('Chris', col)✅✅ ไม่ Match

ข้อจำกัด FIND_IN_SET

  • Delimiter ต้องเป็น Comma (,) เท่านั้น
  • ไม่รองรับ Space: 'Chris, Bob' → ไม่ Match 'Bob' (ต้อง 'Chris,Bob')
  • NULL Input → คืน NULL
  • ไม่ใช้ INDEX ได้
  • haystack > 64KB อาจมีปัญหา (Version ขึ้นอยู่)

แก้ Space: REPLACE ก่อน

WHERE FIND_IN_SET('Bob', REPLACE(username, ', ', ',')) > 0;

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

1. Normalized Table (แนะนำมากที่สุด)

CREATE TABLE user_tags (
    user_id INT,
    tag VARCHAR(50),
    PRIMARY KEY (user_id, tag)
);

2. JSON Column (MySQL 5.7+)

ALTER TABLE demo81 ADD tags JSON;
UPDATE demo81 SET tags = JSON_ARRAY('John','Chris','David') WHERE id = 1;

SELECT * FROM demo81 WHERE JSON_CONTAINS(tags, '"Chris"');

3. Generated Column + Index

ALTER TABLE demo81
ADD COLUMN has_chris BOOLEAN AS (FIND_IN_SET('Chris', username) > 0) STORED,
ADD INDEX idx_has_chris (has_chris);

Dynamic IN List (Application Layer)

ใน Application: Parse String → List → ใช้ IN (?) พร้อม Bind Parameters

String sql = "SELECT * FROM demo81 WHERE FIND_IN_SET(?, username) > 0";
ps.setString(1, "Chris");