Cú pháp
Sử dụng GROUP BY trên nhiều cột kết hợp HAVING COUNT(*) > 1:
SELECT cot1, cot2, ..., cotN, COUNT(*) AS so_lan FROM ten_bang GROUP BY cot1, cot2, ..., cotN HAVING COUNT(*) > 1;
Ví dụ: Kiểm tra trùng lặp FirstName + LastName
1. Tạo bảng
mysql> CREATE TABLE DuplicateDemo ( -> StudentId INT NOT NULL, -> StudentFirstName VARCHAR(100), -> StudentLastName VARCHAR(100), -> PRIMARY KEY(StudentId) -> ); Query OK, 0 rows affected (0.50 sec)
2. Chèn dữ liệu (có trùng lặp)
mysql> INSERT INTO DuplicateDemo VALUES(1,'John','Smith'); Query OK, 1 row affected (0.13 sec) mysql> INSERT INTO DuplicateDemo VALUES(2,'Mike','Jones'); Query OK, 1 row affected (0.28 sec) mysql> INSERT INTO DuplicateDemo VALUES(3,'David','Smith'); Query OK, 1 row affected (0.15 sec) mysql> INSERT INTO DuplicateDemo VALUES(4,'Carol','Taylor'); Query OK, 1 row affected (0.20 sec) mysql> INSERT INTO DuplicateDemo VALUES(5,'David','Smith'); Query OK, 1 row affected (0.11 sec) mysql> INSERT INTO DuplicateDemo VALUES(6,'John','Smith'); Query OK, 1 row affected (0.16 sec) mysql> INSERT INTO DuplicateDemo VALUES(7,'John','Taylor'); Query OK, 1 row affected (0.15 sec)
3. Dữ liệu gốc
mysql> SELECT * FROM DuplicateDemo;
+-----------+------------------+-----------------+ | StudentId | StudentFirstName | StudentLastName | +-----------+------------------+-----------------+ | 1 | John | Smith | | 2 | Mike | Jones | | 3 | David | Smith | | 4 | Carol | Taylor | | 5 | David | Smith | | 6 | John | Smith | | 7 | John | Taylor | +-----------+------------------+-----------------+ 7 rows in set (0.00 sec)
4. Tìm bản ghi trùng FirstName + LastName
mysql> SELECT StudentFirstName, StudentLastName, COUNT(*) AS Total -> FROM DuplicateDemo -> GROUP BY StudentFirstName, StudentLastName -> HAVING COUNT(*) > 1;
+------------------+-----------------+-------+ | StudentFirstName | StudentLastName | Total | +------------------+-----------------+-------+ | John | Smith | 2 | | David | Smith | 2 | +------------------+-----------------+-------+ 2 rows in set (0.00 sec)
Mở rộng: Xem chi tiết các hàng trùng lặp
Cách 1: JOIN ngược lại bảng gốc
SELECT d.*
FROM DuplicateDemo d
INNER JOIN (
SELECT StudentFirstName, StudentLastName
FROM DuplicateDemo
GROUP BY StudentFirstName, StudentLastName
HAVING COUNT(*) > 1
) dup ON d.StudentFirstName = dup.StudentFirstName
AND d.StudentLastName = dup.StudentLastName
ORDER BY d.StudentFirstName, d.StudentLastName;
Cách 2: Window Function (MySQL 8.0+)
SELECT * FROM (
SELECT *,
COUNT(*) OVER (PARTITION BY StudentFirstName, StudentLastName) AS cnt
FROM DuplicateDemo
) t WHERE cnt > 1;
Xóa bản ghi trùng lặp (giữ lại 1)
DELETE d1 FROM DuplicateDemo d1 INNER JOIN DuplicateDemo d2 WHERE d1.StudentId > d2.StudentId AND d1.StudentFirstName = d2.StudentFirstName AND d1.StudentLastName = d2.StudentLastName;
Ngăn chặn trùng lặp: UNIQUE CONSTRAINT
ALTER TABLE DuplicateDemo ADD UNIQUE KEY uk_name (StudentFirstName, StudentLastName);
Lưu ý
GROUP BYnhiều cột = nhóm theo tổ hợp giá trịHAVINGlọc sau khi gom nhóm (khác WHERE lọc trước)- Index trên (FirstName, LastName) tăng tốc truy vấn kiểm tra trùng