Kỹ thuật xóa bản ghi trùng lặp (giữ lại 1 bản ghi mỗi nhóm) bằng DELETE ... LEFT JOIN với subquery lấy ID nhỏ nhất.
Tạo bảng và dữ liệu có trùng
mysql> CREATE TABLE DemoTable(
Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(100)
);
Query OK, 0 rows affected (0.46 sec)
mysql> INSERT INTO DemoTable(FirstName) VALUES
('Chris'), ('Robert'), ('Robert'), ('John'), ('John'), ('Mike');
Query OK, 6 rows affected
Xóa trùng lặp, giữ ID nhỏ nhất
mysql> DELETE tbl FROM DemoTable tbl
LEFT JOIN (
SELECT MIN(Id) AS Id, FirstName
FROM DemoTable
GROUP BY FirstName
) tbl1 ON tbl.Id = tbl1.Id AND tbl.FirstName = tbl1.FirstName
WHERE tbl1.Id IS NULL;
Query OK, 2 rows affected (0.16 sec)
Kết quả (giữ Chris id=1, Robert id=2, John id=4, Mike id=6):
+----+-----------+ | Id | FirstName | +----+-----------+ | 1 | Chris | | 2 | Robert | | 4 | John | | 6 | Mike | +----+-----------+
Giải thích logic:
- Subquery
tbl1lấy ID nhỏ nhất của mỗi FirstName LEFT JOINgiữ lại tất cả hàng củatbl(bảng gốc)WHERE tbl1.Id IS NULLchọn các hàng KHÔNG khớp với ID nhỏ nhất → chính là bản ghi trùng cần xóa
Cách khác (MySQL 8.0+): DELETE FROM DemoTable WHERE Id NOT IN (SELECT MIN(Id) FROM DemoTable GROUP BY FirstName) (cần bật optimizer switch hoặc viết lại tránh lỗi "You can't specify target table for update in FROM clause").