เมื่อมีข้อมูลเก็บเป็น Comma-Separated Values (CSV) ในคอลัมน์เดียว ต้องการดึงค่าแรก (First Element) ให้ใช้ SUBSTRING_INDEX() กำหนด Occurrence = 1
สร้างตารางและข้อมูล CSV
mysql> create table DemoTable (CSV_Value varchar(200));
mysql> insert into DemoTable values('10,20,50,80'),('100,21,51,43'),('1,56,103,1090');
ข้อมูลในตาราง
+---------------+ | CSV_Value | +---------------+ | 10,20,50,80 | | 100,21,51,43 | | 1,56,103,1090 | +---------------+
คำสั่งดึงค่าแรก (Occurrence = 1)
mysql> select SUBSTRING_INDEX(CSV_Value, ',', 1) AS FIRST_ELEMENT from DemoTable;
ผลลัพธ์
+---------------+ | FIRST_ELEMENT | +---------------+ | 10 | | 100 | | 1 | +---------------+
SUBSTRING_INDEX(str, delim, count)
- count > 0 - คืนส่วนซ้าย ตั้งแต่ต้นจนถึงตัวคั่นครั้งที่ count
- count < 0 - คืนส่วนขวา ตั้งแต่ตัวคั่นครั้งที่ |count| จากท้ายจนจบ
- count = 0 - คืนค่าว่าง
ดึง Element ตำแหน่งที่ N (ไม่ใช่แค่ตัวแรก)
MySQL ไม่มีฟังก์ชัน SPLIT_PART ตรงๆ แต่สามารถทำได้ด้วย Nested SUBSTRING_INDEX:
-- Element ที่ 2 (1-based) SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(CSV_Value, ',', 2), ',', -1) AS second_element FROM DemoTable;
+----------------+ | second_element | +----------------+ | 20 | | 21 | | 56 | +----------------+
Generic Function สำหรับ Element ที่ N
CREATE FUNCTION `get_csv_element`(csv TEXT, delim VARCHAR(10), pos INT) RETURNS TEXT DETERMINISTIC RETURN SUBSTRING_INDEX(SUBSTRING_INDEX(csv, delim, pos), delim, -1);
คำเตือน: CSV ในคอลัมน์เดียว (Anti-pattern)
- ละเมิด Normalization (1NF)
- Query ช้า ไม่ใช้ Index ได้
- ยากต่อการ UPDATE/DELETE ค่าเดี่ยว
- แนะนำ: สร้างตาราง Child แยก (One-to-Many)
- MySQL 8.0+ ใช้ JSON Array + JSON_EXTRACT() / JSON_TABLE() ดีกว่า
MySQL 8.0+ JSON Way
-- เก็บเป็น JSON Array
INSERT INTO DemoTable(json_col) VALUES ('[10, 20, 50, 80]');
-- ดึง Element แรก (0-based index)
SELECT JSON_EXTRACT(json_col, '$[0]') AS first_element FROM DemoTable;
-- หรือ
SELECT json_col->>'$[0]' AS first_element FROM DemoTable;