Dưới đây là sáu ví dụ xóa các hàng trùng lặp khỏi bảng trong SQLite khi các hàng đó có khóa chính hoặc cột định danh duy nhất.
Trong những trường hợp này, khóa chính phải được bỏ qua khi so sánh các bản sao (do thực tế là các khóa chính ngăn các hàng trùng lặp theo định nghĩa).
Dữ liệu Mẫu
Các ví dụ của chúng tôi sử dụng dữ liệu sau:
SELECT * FROM Dogs;
Kết quả:
DogId FirstName LastName ----- --------- -------- 1 Bark Smith 2 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag Johnson 6 Wag Johnson 7 Wag JohnsonChúng ta có thể thấy rằng hai hàng đầu tiên chứa các bản sao, ba hàng cuối cùng cũng vậy.
DogId
cột chứa các giá trị duy nhất (vì đó là khóa chính của bảng) và do đó, nói đúng ra, không có bản sao. Nhưng trong các tình huống thực tế, bạn thường muốn loại bỏ các bảng có chứa khóa chính. Do đó, trong các ví dụ sau, chúng tôi bỏ qua khóa chính và xóa các hàng chứa giá trị trùng lặp trên các cột còn lại.Tùy chọn 1
Đây là tùy chọn đầu tiên của chúng tôi để loại bỏ lừa đảo trong bảng trên:
DELETE FROM Dogs WHERE DogId IN ( SELECT DogId FROM Dogs EXCEPT SELECT MIN(DogId) FROM Dogs GROUP BY FirstName, LastName ); SELECT * FROM Dogs;
Kết quả:
DogId FirstName LastName ----- --------- -------- 1 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag JohnsonBảng đã được gỡ bỏ như mong đợi.
Ngoài ra, chúng ta có thể sử dụng
MAX()
thay vìMIN()
chức năng để thay đổi các hàng bị xóa. Tôi sẽ làm điều này trong ví dụ tiếp theo.Tùy chọn 2
Trong ví dụ này (và các ví dụ sau), chúng tôi sẽ giả định rằng bảng đã được khôi phục về trạng thái ban đầu (với các bản sao).
Đây là một truy vấn khác xóa các hàng trùng lặp và chọn các hàng còn lại:
DELETE FROM Dogs WHERE DogId IN ( SELECT d2.DogId FROM Dogs d1, Dogs d2 WHERE d1.FirstName = d2.FirstName AND d1.LastName = d2.LastName AND d1.DogId <> d2.DogId AND d1.DogId=( SELECT MAX(DogId) FROM Dogs d3 WHERE d3.FirstName = d1.FirstName AND d3.LastName = d1.LastName ) ); SELECT * FROM Dogs;
Kết quả:
DogId FirstName LastName ----- --------- -------- 2 Bark Smith 3 Woof Jones 4 Ruff Robinson7 Wag JohnsonBảng hiện đã được gỡ bỏ.
Lưu ý rằng tôi đã sử dụng
MAX()
hàm thay vìMIN()
mà tôi đã sử dụng trong ví dụ trước. Chúng ta có thể thấy ảnh hưởng của điều này đối với hoạt động khử lừa đảo. Nó đã xóa các hàng khác nhau khỏi bảng.Tùy chọn 3
Đây là một tùy chọn không yêu cầu sử dụng
MIN()
hoặcMAX()
:DELETE FROM Dogs WHERE EXISTS ( SELECT 1 FROM Dogs d2 WHERE Dogs.FirstName = d2.FirstName AND Dogs.LastName = d2.LastName AND Dogs.DogId > d2.DogId ); SELECT * FROM Dogs;
Kết quả:
DogId FirstName LastName ----- --------- -------- 1 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag JohnsonTùy chọn 4
Đây là một tùy chọn khác:
DELETE FROM Dogs WHERE DogId > ( SELECT MIN(DogId) FROM Dogs d2 WHERE Dogs.FirstName = d2.FirstName AND Dogs.LastName = d2.LastName ); SELECT * FROM Dogs;
Kết quả:
DogId FirstName LastName ----- --------- -------- 1 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag JohnsonTùy chọn 5
Theo mặc định, mỗi hàng trong SQLite có một cột đặc biệt, thường được gọi là
rowid
, xác định duy nhất hàng đó trong bảng. Trừ khi nó đã bị xóa khỏi bảng một cách rõ ràng, bạn có thể sử dụng nó làm số nhận dạng duy nhất cho mỗi hàng. Phương pháp này có thể hữu ích nếu bạn không thể tham chiếu khóa chính vì lý do nào đó (hoặc nếu bảng không có khóa chính).Do đó, chúng tôi có thể sử dụng
rowid
trong truy vấn của chúng tôi thay vìDogId
cột:DELETE FROM Dogs WHERE EXISTS ( SELECT 1 FROM Dogs d2 WHERE Dogs.FirstName = d2.FirstName AND Dogs.LastName = d2.LastName AND Dogs.rowid > d2.rowid ); SELECT * FROM Dogs;
Kết quả:
DogId FirstName LastName ----- --------- -------- 1 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag JohnsonTùy chọn 6
Và đây là ví dụ khác, nhưng với
rowid
thay vì khóa chính:DELETE FROM Dogs WHERE rowid > ( SELECT MIN(rowid) FROM Dogs d2 WHERE Dogs.FirstName = d2.FirstName AND Dogs.LastName = d2.LastName ); SELECT * FROM Dogs;
Kết quả:
DogId FirstName LastName ----- --------- -------- 1 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag Johnson