Mükerrer Kayıtlar Nasıl Bulunur, Güvenle Nasıl Silinir?
Beceri rehberi

Mükerrer Kayıtlar Nasıl Bulunur, Güvenle Nasıl Silinir?

Hazırlayan: Mindset Institute EditörlüğüGüncellendi: 5 dk okuma

Mükerrer satırları GROUP BY, HAVING ve ROW_NUMBER ile bulup güvenle silmeyi, silmeden önce kontrol adımlarını ve tekrarı önleyen kısıtları öğrenin.

Tekrar eden kayıt ne demektir?

Tekrar eden (mükerrer) kayıt, aynı gerçek dünya nesnesini temsil eden birden fazla satırdır. Önce neyin tekrar sayılacağını netleştirmek gerekir, çünkü bu karar sorgunun tamamını belirler. Satırın tamamı aynıysa kayıt birebir kopyadır. Çoğu durumda ise satırlar farklı bir kimlik numarası taşır, ama müşteri e-postası, kimlik numarası ya da sipariş kodu gibi iş açısından anlamlı sütunlar aynıdır.

Bu yüzden ilk soru şudur: hangi sütun ya da sütun kombinasyonu bir kaydı benzersiz kılıyor? Müşteri tablosunda e-posta, sipariş kalemlerinde sipariş numarası ile ürün kodu birlikte, günlük kayıt tablosunda kullanıcı ile tarih birlikte anahtar olabilir.

Tekrarlar genelde şu kaynaklardan gelir: aynı dosyanın birden fazla kez içe aktarılması, uygulamada çift tıklama ile gönderilen formlar, farklı sistemlerden gelen verilerin birleştirilmesi ve tabloda benzersizlik kısıtının bulunmaması. Kaynağı anlamak, temizlikten sonra tekrarın geri gelmesini engellemek için gereklidir.

Tekrarları bulmak: GROUP BY ve HAVING

En yaygın yöntem, tekrar sayılan sütunlara göre gruplayıp grup büyüklüğüne bakmaktır. Kalıp şöyledir: SELECT ile e-posta sütununu ve COUNT(*) değerini seçersiniz, FROM müşteriler yazarsınız, GROUP BY e-posta ile gruplarsınız ve HAVING COUNT(*) ifadesini birden büyük olacak şekilde yazarsınız. Sonuçta yalnızca birden fazla kez geçen e-postalar ve kaç kez geçtikleri görünür.

HAVING, gruplama sonrası filtre uygular; WHERE ise gruplamadan önce satırları eler. Sayıya göre filtre mutlaka HAVING ile yapılır.

Birden çok sütunun birlikte tekrar etmesi isteniyorsa tüm sütunları hem SELECT hem GROUP BY satırına yazarsınız. Tekrar eden değerlerin tüm satır ayrıntısını görmek içinse bu sorguyu alt sorgu olarak kullanıp asıl tabloyla JOIN edersiniz. Böylece hangi kimlik numaralarının aynı e-postayı paylaştığını yan yana inceleyebilirsiniz.

Hangi satırın kalacağına karar vermek: ROW_NUMBER

Silmeden önce her tekrar grubundan hangi satırın korunacağı belirlenmelidir. Pencere fonksiyonu ROW_NUMBER bunu açık biçimde yapar. Sorguda ROW_NUMBER() OVER (PARTITION BY e-posta ORDER BY olusturma_tarihi) ifadesini kullanırsınız. PARTITION BY tekrar tanımını, ORDER BY ise korunacak satırı belirler: en eski kaydı tutmak için tarihe göre artan, en güncelini tutmak için azalan sıralarsınız.

Bu ifade her gruptaki satırlara sırayla numara verir. Numarası birden büyük olan satırlar silinecek adaylardır, ilk sıradaki satır korunur. Bu sorguyu bir CTE ya da alt sorgu içine alıp dışarıdan sıra numarasına göre filtrelediğinizde silinecek satırların listesini SELECT ile görebilirsiniz.

Sıralama ölçütünü bilinçli seçin. Aynı e-postalı kayıtlardan hangisi daha eksiksiz, hangisi son güncellenen, hangisine başka tablolar bağlı? Bu soruların yanıtı, sıralamadaki ORDER BY ifadesine dönüşür. Eşit değerler varsa sıralamayı belirleyici kılmak için kimlik sütununu da ekleyin.

Güvenli silme adımları

Tekrarları silmek, geri dönüşü zor bir işlemdir. Şu sırayı izlemek veri kaybını önler: • Önce yedek alın ya da tablonun bir kopyasını ayrı bir tabloya yazın. • Silinecek satırları SELECT ile listeleyin ve sayısını not edin; beklediğiniz sayıyla uyuşuyor mu? • Silinecek satırlara başka tabloların yabancı anahtarla bağlı olup olmadığını kontrol edin. Bağlı kayıtlar varsa önce onları korunacak satıra taşıyın. • İşlemi transaction içinde çalıştırın; silme sonrası satır sayısı beklentiyle uyuşmuyorsa ROLLBACK yapın. • DELETE komutunun WHERE ve filtre mantığını SELECT'te kullandığınız ifadeyle aynı tutun. • Silmeden sonra tekrar bulma sorgusunu çalıştırıp sonucun boş döndüğünü doğrulayın.

SQL Server'da silinecek satırları bir CTE içinde seçip doğrudan CTE üzerinden DELETE çalıştırabilirsiniz. PostgreSQL'de silinecek kimlikleri alt sorguyla seçip DELETE ... WHERE id IN kalıbı kullanılır. MySQL'de ise kimlikleri türetilmiş tablo içinde toplamak ya da self join ile silmek gerekir; sözdizimi sürüme göre değiştiği için sisteminizin dokümantasyonunu kontrol edin.

Örnek senaryo: müşteri listesi temizliği

Örneğin bir CRM'den dışa aktarılan müşteri tablosunu yeni bir veritabanına yanlışlıkla tekrar tekrar yüklediniz ve e-posta başına birden fazla satır oluştu. Önce GROUP BY ve HAVING ile tekrar eden e-postaları listeler, kaç e-postanın etkilendiğini görürsünüz. Ardından ROW_NUMBER ile her e-posta grubunda en eski kaydı ilk sıraya alırsınız.

Silmeden önce bu satırların başka tablolarda, örneğin siparişlerde kullanılıp kullanılmadığına bakarsınız. Siparişler silinecek bir kimliğe bağlıysa önce sipariş tablosundaki müşteri kimliğini korunacak kimliğe güncellersiniz; aksi halde ya silme yabancı anahtar hatasıyla durur ya da sipariş geçmişi yetim kalır.

Son olarak transaction içinde silme komutunu çalıştırır, satır sayısını kontrol eder, işlemi onaylar ve tablodaki e-posta sütununa benzersizlik kısıtı eklersiniz. Kısıt eklemeden önce temizlik bitmiş olmalıdır; yoksa kısıt oluşturma komutu mevcut tekrarlar yüzünden hata verir.

Tekrarı sadece görünümde gizlemek: DISTINCT

Bazen veriyi silmek istemezsiniz, yalnızca raporda tekrarları göstermek istemezsiniz. DISTINCT, seçilen sütunların birebir aynı olduğu satırları tek bir kez gösterir. Hızlı ve basittir, ancak yalnızca seçtiğiniz sütunlara bakar; kimlik gibi farklı bir sütunu da seçerseniz hiçbir satır tekrar sayılmaz.

DISTINCT ile ROW_NUMBER arasındaki tercih şudur: yalnızca ayrık değerlerin listesi gerekiyorsa DISTINCT yeterlidir. Her tekrar grubundan hangi satırın seçileceğini kontrol etmek, ya da satırın diğer sütunlarını da korumak gerekiyorsa ROW_NUMBER kullanılır.

GROUP BY ile MIN ya da MAX kullanmak da bir alternatiftir. Örneğin her e-posta için en küçük kimliği bulup yalnızca onu tutmak, silme kriteri olarak kullanılabilir. Bu yöntem sade bir mantık sunar; ancak sıralama ölçütünüz tarihe ya da başka bir sütuna dayanıyorsa pencere fonksiyonu daha esnektir.

Tekrarın geri gelmesini önlemek

Temizlik tek seferlik bir çözümdür; kaynak düzeltilmezse tekrarlar yeniden birikir. En sağlam önlem, tabloda benzersizlik kısıtı (UNIQUE) ya da birincil anahtar tanımlamaktır. Böylece veritabanı aynı değeri yeniden eklemeyi reddeder. Bileşik anahtarlar, tek sütunun yetmediği durumlarda birkaç sütunu birlikte benzersiz kılar.

Veri yüklemelerinde, hedef tabloya doğrudan yazmak yerine önce bir ara tabloya yükleyip tekrarları orada temizlemek ve sonra yalnızca yeni kayıtları eklemek iyi bir pratiktir. Birçok sistem ayrıca çakışmada güncelle ya da yoksay anlamına gelen komutlar (UPSERT, MERGE, ON CONFLICT gibi) sunar.

Mindset kataloğunda SQL ile Veri Sorgulama (Temel) eğitimi filtreleme, toplulaştırma ve gruplama modüllerini; SQL ile Programlama Eğitimi ise Veri İşleme Dili, Toplama ve Gruplama modüllerini içerir. Bu modüller, veri temizliği yapan analist ve raporlama ekipleri için buradaki sorguların temelini oluşturur.

İlgili Mindset programı

SQL ile Veri Sorgulama (Temel)

Sık sorulanlar

Sık sorulan sorular

Tekrar eden kayıtları DELETE ile tek komutta silebilir miyim?

Yapabilirsiniz, ama silinecek satırları önce SELECT ile görmeden yapmayın. Tek komutta silmek için ROW_NUMBER ile numaralanmış bir CTE ya da alt sorgu üzerinden numarası birden büyük olan satırları hedeflersiniz. Sözdizimi veritabanı sistemine göre değişir. Çalıştırmadan önce yedek alın ve işlemi transaction içinde yürütün.

Tüm sütunları aynı olan satırlar nasıl bulunur?

Tablodaki bütün sütunları GROUP BY listesine yazıp HAVING ile grup büyüklüğünün birden fazla olduğunu filtrelersiniz. Sütun çok ise ROW_NUMBER içindeki PARTITION BY ifadesinde hepsini sıralamak gerekebilir. Kimlik gibi her satırda farklı olan sütunu bu listeye eklemeyin, aksi halde hiçbir satır tekrar sayılmaz.

Tekrarları silerken en güncel kaydı nasıl korurum?

ROW_NUMBER içindeki ORDER BY ifadesini güncelleme ya da oluşturma tarihine göre azalan sıralayın. Böylece her grupta en yeni kayıt ilk sırada olur ve silme koşulu yalnızca numarası birden büyük olanları hedefler. Eşit tarihlerde belirleyici olması için kimlik sütununu da sıralamaya ekleyin.

NULL değerler tekrar sayılır mı?

GROUP BY NULL değerleri aynı grup sayar, yani boş e-postaya sahip tüm satırlar tek grupta toplanır. Oysa UNIQUE kısıtı çoğu sistemde NULL değerleri farklı kabul eder, ancak bu davranış sisteme göre değişir. Boş değerleri tekrar saymak istemiyorsanız sorguya açık bir IS NOT NULL koşulu ekleyin.

Silmek yerine tekrarları işaretlemek daha mı güvenli?

Çoğu zaman evet. Tabloya bir bayrak sütunu ekleyip tekrar sayılan satırları işaretlemek ve raporlarda onları filtrelemek, silmeyi geri alınabilir kılar. Kalıcı silme, sonuçlar kontrol edildikten sonra yapılır.

SQL'de Tekrar Eden Kayıtları Bulma ve Silme