Contoh berikut menggunakan T-SQL untuk menghapus baris duplikat di SQL Server sambil mengabaikan kunci utama atau kolom pengenal unik.
Lebih khusus lagi, contoh menghapus baris duplikat tetapi menyimpannya. Jadi, mengingat dua baris identik, satu dihapus dan yang lainnya tetap. Ini sering disebut sebagai "de-duping" tabel, "deduplikasi" tabel, dll.
Contoh Data
Misalkan kita memiliki tabel dengan data berikut:
SELECT * FROM Dogs;
Hasil:
+---------+-------------+------------+ | DogId | FirstName | LastName | |---------+-------------+------------| | 1 | Bark | Smith | | 2 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 5 | Wag | Johnson | | 6 | Wag | Johnson | | 7 | Wag | Johnson | +---------+-------------+------------+
Kita dapat melihat bahwa dua baris pertama adalah duplikat, begitu pula tiga baris terakhir.
Opsi 1
Pertama, jalankan kode berikut untuk memeriksa baris mana yang akan di-de-duped:
WITH cte AS
(
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY FirstName, LastName
ORDER BY FirstName, LastName
) AS Row_Number
FROM Dogs
)
SELECT * FROM cte WHERE Row_Number <> 1;
Hasil:
+---------+-------------+------------+--------------+ | DogId | FirstName | LastName | Row_Number | |---------+-------------+------------+--------------| | 2 | Bark | Smith | 2 | | 6 | Wag | Johnson | 2 | | 7 | Wag | Johnson | 3 | +---------+-------------+------------+--------------+
Kami menggunakan ROW_NUMBER()
fungsi dengan PARTITION BY
klausa untuk membuat nomor baris kita sendiri yang bertambah ketika ada duplikat ditemukan, dan diatur ulang ketika non-duplikat ditemukan. Angka yang lebih besar dari 1 menunjukkan bahwa itu duplikat, jadi kami hanya menampilkan baris yang memiliki angka lebih besar dari 1.
Kita dapat melihat bahwa tiga baris akan dihapus saat kita menghapus penipuan pada tabel ini.
Sekarang mari kita de-dupe tabel:
WITH cte AS
(
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY FirstName, LastName
ORDER BY FirstName, LastName
) AS Row_Number
FROM Dogs
)
DELETE FROM cte WHERE Row_Number <> 1;
Hasil:
(3 rows affected)
Seperti yang diharapkan, tiga baris telah dihapus.
Permintaan ini hampir identik dengan yang sebelumnya. Yang kami lakukan hanyalah mengubah SELECT *
pada baris terakhir ke DELETE
.
Sekarang mari kita pilih semua baris dari tabel untuk memverifikasi bahwa baris yang benar telah dihapus:
SELECT * FROM Dogs;
Hasil:
+---------+-------------+------------+ | DogId | FirstName | LastName | |---------+-------------+------------| | 1 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 5 | Wag | Johnson | +---------+-------------+------------+
Kita dapat melihat bahwa setiap anjing sekarang hanya muncul sekali di tabel.
Opsi 2
Dengan asumsi bahwa tabel telah dipulihkan setelah contoh sebelumnya, berikut cara lain untuk memeriksa duplikat:
SELECT * FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
EXCEPT SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
Hasil:
+---------+-------------+------------+ | DogId | FirstName | LastName | |---------+-------------+------------| | 2 | Bark | Smith | | 6 | Wag | Johnson | | 7 | Wag | Johnson | +---------+-------------+------------+
Dalam hal ini, kami menggunakan EXCEPT
operator bersama dengan MIN()
fungsi. Kita bisa mengganti MIN()
dengan MAX()
tergantung pada baris mana yang ingin kita hapus.
Untuk menghapus baris, kita cukup mengganti SELECT *
dengan DELETE
:
DELETE FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
EXCEPT SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
Hasil:
(3 rows affected)
Dan periksa untuk melihat apa yang tersisa:
SELECT * FROM Dogs;
Hasil:
+---------+-------------+------------+ | DogId | FirstName | LastName | |---------+-------------+------------| | 1 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 5 | Wag | Johnson | +---------+-------------+------------+
Opsi 3
Cara lain untuk melakukannya adalah dengan menggabungkan tabel itu sendiri dan memeriksa duplikat dengan cara itu.
Dengan asumsi bahwa tabel telah dipulihkan setelah contoh sebelumnya, inilah opsi ketiga kami untuk memilih duplikat:
SELECT *
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
);
Hasil:
+---------+-------------+------------+---------+-------------+------------+ | DogId | FirstName | LastName | DogId | FirstName | LastName | |---------+-------------+------------+---------+-------------+------------| | 2 | Bark | Smith | 1 | Bark | Smith | | 7 | Wag | Johnson | 5 | Wag | Johnson | | 7 | Wag | Johnson | 6 | Wag | Johnson | +---------+-------------+------------+---------+-------------+------------+
Hasil ini tidak sejelas pada contoh sebelumnya, tetapi kita masih dapat melihat baris mana yang merupakan duplikat.
Sekarang kita dapat memodifikasi kueri itu sehingga kita menghapus baris duplikat:
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
)
);
Hasil:
(3 rows affected)
Sekali lagi, tiga baris dihapus.
Mari kita periksa lagi tabelnya:
SELECT * FROM Dogs;
Hasil:
+---------+-------------+------------+ | DogId | FirstName | LastName | |---------+-------------+------------| | 2 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 7 | Wag | Johnson | +---------+-------------+------------+
Anda mungkin memperhatikan bahwa kali ini baris lain telah dihapus. Dengan kata lain, kita sekarang memiliki DogId
s 2, 3, 4, dan 7 sedangkan pada contoh sebelumnya kita dibiarkan dengan 1, 3, 4, dan 5.
Kita dapat dengan mudah mengubah contoh ini untuk menghapus baris yang sama seperti contoh sebelumnya. Untuk melakukan ini, kita dapat menggunakan MIN()
fungsi alih-alih MAX()
fungsi:
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 MIN(DogId)
FROM Dogs d3
WHERE d3.FirstName = d1.FirstName
AND d3.LastName = d1.LastName
)
);