Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MySQL

Cách kiểm tra trùng lặp trên nhiều cột trong MySQL


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 BY nhiều cột = nhóm theo tổ hợp giá trị
  • HAVING lọ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