Khi cần tìm các hàng mà cột chứa danh sách giá trị phân cách bằng dấu phẩy (CSV) có chứa một giá trị cụ thể, dùng REGEXP với biểu thức chính quy chính xác để tránh khớp nhầm (ví dụ: tìm '90' không khớp '190').
Ví dụ minh họa
Tạo bảng:
mysql> CREATE TABLE DemoTable1447 (
Value VARCHAR(100)
);
Chèn dữ liệu CSV:
mysql> INSERT INTO DemoTable1447 VALUES ('19,58,90,56');
mysql> INSERT INTO DemoTable1447 VALUES ('56,89,99,100');
mysql> INSERT INTO DemoTable1447 VALUES ('75,76,65,90');
mysql> INSERT INTO DemoTable1447 VALUES ('101,54,57,59');
Dữ liệu:
mysql> SELECT * FROM DemoTable1447;
+--------------+ | Value | +--------------+ | 19,58,90,56 | | 56,89,99,100 | | 75,76,65,90 | | 101,54,57,59 | +--------------+
Tìm hàng chứa giá trị 90 (đúng ranh giới)
mysql> SELECT * FROM DemoTable1447
WHERE Value REGEXP '(^|,)90($|,)';
Kết quả (2 hàng có 90):
+-------------+ | Value | +-------------+ | 19,58,90,56 | | 75,76,65,90 | +-------------+
Giải thích REGEXP '(^|,)90($|,)'
^: Đầu chuỗi.$: Cuối chuỗi.(^|,): Khớp đầu chuỗi HOẶC dấu phẩy trước giá trị.90: Giá trị cần tìm.($|,): Khớp cuối chuỗi HOẶC dấu phẩy sau giá trị.- → Đảm bảo khớp chính xác '90' như một phần tử riêng biệt, không khớp '190', '901', v.v.
So sánh các phương pháp tìm trong CSV
| Phương pháp | Cú pháp | Độ chính xác | Hiệu năng |
|---|---|---|---|
REGEXP | WHERE col REGEXP '(^|,)val($|,)' | ✅ Cao | Trung bình (không dùng index) |
FIND_IN_SET | WHERE FIND_IN_SET('val', col) > 0 | ✅ Cao | Trung bình |
LIKE | WHERE col LIKE '%,val,%' OR ... | ⚠️ Dễ sai (cần 4 điều kiện) | Nhanh nhưng phức tạp |
| JSON (MySQL 5.7+) | WHERE JSON_CONTAINS(col_json, '\"val\"') | ✅ Cao + có index | Tốt nhất cho dữ liệu mới |
Khuyến nghị thiết kế
Tránh lưu CSV trong cột đơn. Nên:
- Chuẩn hóa: Tạo bảng con (1-N hoặc N-N).
- Kiểu JSON: MySQL 5.7+ hỗ trợ JSON gốc, có index, truy vấn mạnh.