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

ดึงค่าแรกจากรายการคั่นจุลภาคใน MySQL ด้วย SUBSTRING_INDEX

เมื่อมีข้อมูลเก็บเป็น 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;