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

ค้นหาข้อมูลในคอลัมน์ที่คั่นด้วย Pipe (|) ด้วย REGEXP ใน MySQL


ปัญหา

ข้อมูลในคอลัมน์หนึ่งเก็บหลายค่าคั่นด้วย Pipe (|) เช่น 8|56|78|45 ต้องการค้นหาแถวที่มีค่าเฉพาะ (เช่น 8) แต่ไม่ต้องการจับค่าที่เป็นส่วนหนึ่งของตัวเลขอื่น (เช่น 18, 88, 98)

วิธีแก้: ใช้ Regular Expression (REGEXP)

ใช้ Pattern \\|8\\| เพื่อจับค่า 8 ที่อยู่ระหว่าง Pipe ทั้งสองข้าง (Escaped backslash เนื่องจาก Pipe เป็น Special character ใน Regex)

ตัวอย่างการใช้งาน

1. สร้างตาราง

mysql> CREATE TABLE DemoTable (
    -> Value VARCHAR(60)
    -> );
Query OK, 0 rows affected (0.48 sec)

2. เพิ่มข้อมูลทดสอบ

mysql> INSERT INTO DemoTable VALUES('8|56|78|45');
Query OK, 1 row affected (0.24 sec)
mysql> INSERT INTO DemoTable VALUES('9876');
Query OK, 1 row affected (0.11 sec)
mysql> INSERT INTO DemoTable VALUES('98|8');
Query OK, 1 row affected (0.17 sec)
mysql> INSERT INTO DemoTable VALUES('3|8|9');
Query OK, 1 row affected (0.13 sec)
mysql> INSERT INTO DemoTable VALUES('97|94');
Query OK, 1 row affected (0.17 sec)
mysql> INSERT INTO DemoTable VALUES('103|104|110|8|97');
Query OK, 1 row affected (0.10 sec)

3. แสดงข้อมูลทั้งหมด

mysql> SELECT * FROM DemoTable;

ผลลัพธ์:

+------------------+
| Value            |
+------------------+
| 8|56|78|45       |
| 9876             |
| 98|8             |
| 3|8|9            |
| 97|94            |
| 103|104|110|8|97 |
+------------------+
6 rows in set (0.00 sec)

4. ค้นหาแถวที่มีค่า 8 แยกต่างหาก (ไม่ใช่ส่วนหนึ่งของตัวเลขอื่น)

mysql> SELECT * FROM DemoTable
    -> WHERE Value REGEXP '\\|8\\|';

ผลลัพธ์:

+------------------+
| Value            |
+------------------+
| 3|8|9            |
| 103|104|110|8|97 |
+------------------+
2 rows in set (0.00 sec)

Pattern ที่ใช้

Pattern ความหมาย จับได้ ไม่จับ
\\|8\\| 8 ระหว่าง Pipe 3|8|9, 103|...|8|97 8|56, 98|8, 9876
^8\\| เริ่มต้นด้วย 8| 8|56|78|45 อื่นๆ
\\|8$ จบด้วย |8 98|8 อื่นๆ
(^|\\|)8(\\|$) 8 แยกต่างหาก (เริ่ม/กลาง/ท้าย) ทั้ง 4 แถวที่มี 8 9876, 97|94

ข้อควรระวัง

  • REGEXP ไม่ใช้ Index ได้ → Full table scan (ช้าบนตารางใหญ่)
  • ควร Normalize ข้อมูล (แยกคอลัมน์/ตาราง) หากค้นหาบ่อย
  • MySQL 8.0+ รองรับ REGEXP_REPLACE() สำหรับแทนที่
  • ใช้ RLIKE เป็น Alias ของ REGEXP

แนวทางแก้ไขระยะยาว

ออกแบบฐานข้อมูลให้เป็น Normalized Form (1NF) โดยแยกค่าที่คั่นด้วย Pipe ออกเป็นตารางความสัมพันธ์ (Many-to-Many) จะทำให้ Query เร็วขึ้นและรักษาความสมบูรณ์ของข้อมูลได้ดีกว่า