Vấn đề
Cột lưu chuỗi phân cách bằng dấu phẩy (CSV), cần đếm số phần tử cho một ID cụ thể.
Giải pháp: CHAR_LENGTH() - CHAR_LENGTH(REPLACE())
Công thức: (CHAR_LENGTH(str) - CHAR_LENGTH(REPLACE(str, delim, ''))) + 1
Ví dụ minh họa
Tạo bảng và dữ liệu
mysql> CREATE TABLE DemoTable (
Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Subject LONGTEXT
);
mysql> INSERT INTO DemoTable(Subject) VALUES('MySQL,MongoDB');
mysql> INSERT INTO DemoTable(Subject) VALUES('MySQL,MongoDB');
mysql> INSERT INTO DemoTable(Subject) VALUES('MongoDB');
mysql> INSERT INTO DemoTable(Subject) VALUES('MySQL');
Dữ liệu gốc
+----+---------------+ | Id | Subject | +----+---------------+ | 1 | MySQL,MongoDB | | 2 | MySQL,MongoDB | | 3 | MongoDB | | 4 | MySQL | +----+---------------+
Truy vấn đếm cho Id = 1
mysql> SELECT
-> Id,
-> CHAR_LENGTH(Subject) - CHAR_LENGTH(REPLACE(Subject, ',', '')) + 1 AS FreqSubject
-> FROM DemoTable
-> WHERE CHAR_LENGTH(Subject) > 0 AND Id = 1;
Kết quả
+----+-------------+ | Id | FreqSubject | +----+-------------+ | 1 | 2 | +----+-------------+
Giải thích công thức
Subject = 'MySQL,MongoDB' -- CHAR_LENGTH = 15 REPLACE(Subject, ',', '') -- 'MySQLMongoDB' = 12 15 - 12 = 3 (số dấu phẩy) + 1 = 4? SAI! Thực tế là 2 phần tử CHỈNH SỬA: 'MySQL,MongoDB' length = 13 (M-y-S-Q-L-,-M-o-n-g-o-D-B) REPLACE = 'MySQLMongoDB' = 11 13 - 11 = 2 dấu phẩy? KHÔNG, chỉ 1 dấu phẩy 2 - 1 = 1? CÒN SAI ĐÚNG: 'MySQL,MongoDB' = 13 ký tự REPLACE = 11 ký tự 13 - 11 = 2 (số ký tự bị xóa = số dấu phẩy) + 1 = 2 phần tử ✓
Cải tiến: Hàm reusable
CREATE FUNCTION CountDelimited(str TEXT, delim VARCHAR(10))
RETURNS INT
DETERMINISTIC
RETURN
CASE
WHEN str IS NULL OR str = '' THEN 0
ELSE CHAR_LENGTH(str) - CHAR_LENGTH(REPLACE(str, delim, '')) + 1
END;
Sử dụng:
SELECT CountDelimited(Subject, ',') FROM DemoTable WHERE Id = 1;
⚠️ Cảnh báo thiết kế
Lưu CSV trong cột vi phạm 1NF. Khuyến nghị tách bảng:
CREATE TABLE Subjects (
Id INT PRIMARY KEY,
Subject VARCHAR(50)
);
-- Mỗi dòng một subject, dùng COUNT(*) GROUP BY Id
Lưu ý CHAR_LENGTH vs LENGTH
CHAR_LENGTH(): Số ký tự (đúng cho UTF-8 multi-byte)LENGTH(): Số byte (sai cho UTF-8 có tiếng Việt)- Luôn dùng
CHAR_LENGTH()cho đếm ký tự