inicio mail me! sindicaci;ón

Archive for SQL

Belirlediğiniz Kolonlara Göre Tekrarlayan Satırları İlgili Tablodan Silmek (Delete Duplicate Rows in a Table)

Zaman zaman veritabanına script geçerken use BuVeritabanı yerine use ŞuVeritabanı diyerek, tablolarda birden fazla tekrarlayan alana sebebiyet vermem nedeniyle bu tekrarlayan alanları silecek bir SP (Store procedure) yazmaya karar verdim. Önceden basit bir sql sorgusu ile bunu hallederken, daha dinamik birşeyler oluşturmak istedim ve herşey bununla başladı. Bir yandan yeni birşeyler öğrenirken, diğer yandan bildiklerimi pekiştirme fırsatı buldum.

1- Sql cümlelerinde from’dan sonra @Degisken kullanamıyoruz. Örn: (Select * from @TableName — HATALI)
2- Temp tablolar mevcut tablonun kopyasını oluşturur, onları işaret etmezler. Bu da temp tablolar üzerinde yapılacak delete, update, insert gibi işlemlerin yalnızca temp tabloya etki edeceğiniz.
3- View ise ilgili tablodaki alanlara işaret eder. Tablo güncellendiği an view güncellenir ; view’de bir işlem yapılırsa asıl tablo güncellenir.

Aşağıdaki store procedure ilk parametre olarak tablo adı, ikinci parametre olarak bir ya da birden fazla kolon adı, üçüncü parameter olarak hangi kolona göre sıralama yapacağı, son olarak da bu sıralamanın artan mı(ASC) azalan mı(DESC) olacağını belirtiyor. 3. ve 4. parametre opsiyonel olmakla birlikte, girilmedikleri takdirde mevcut sıra korunarak işlem yapılıyor.

Sonuç olarak ilgili tablo için kolon adlarına göre gruplandırma yaparak, tekrarlayan alanları buluyor ve siliyoruz.


	create proc DeleteDuplicateRows
	(
		@TableName varchar(100),
		@Columns varchar(100),
		@OrderBy varchar(100) = '(select 0)',
		@Sort varchar(10) = ''
	)
	as
		declare @Sql varchar(max)
		set @Sql = 'create view DuplicatedValueView select ROW_NUMBER() over (partition by ' + @Columns + ' order by ' + @OrderBy + ' ' + @Sort + ') as RowNumber from ' + @TableName
		exec(@sql)
		set @Sql = 'delete from DuplicatedValueView where RowNumber > 1'
		exec(@Sql)
		set @Sql = 'drop view DuplicatedValueView'
		exec(@Sql)

Aşağıdaki sorgu ile ilk adı, soyadı ve doğum tarihi alanlarına göre partition by özelliğini kullanarak gruplandırma yapıyoruz. Bu gruplandırmayı da eklenme tarihine göre artan sırayla sıralıyoruz. İlk ad, soyad ve doğum tarihi aynı olan satırlardan sonradan eklenmiş olan satırların tümünü siliyoruz.

exec DeleteDublicateRows 'Member','FirstName, LastName, Birthdate', 'InsertTime', 'ASC'

İyi çalışmalar,

Bir Veritabanındaki Tabloyu Sql İfadesi ile Farklı Bir Veritabanına Kopyalama

Sql Server’da herhangi bir veritabanındaki bir tabloyu verileriyle ya da verileri olmadan başka bir veritabanında da oluşturmak istediğimde genellikle Sql Server’ın Generate Scripts özelliğinden yararlanıyordum. Ancak bu işlemi direkt olarak bir sql ifadesi yazarak yapmak da mümkün.

Select * Into YeniTestDB.dbo.YeniFilmler
         From Filmler
         Where 1 = 2

Bu ifade ile Filmler isimli tablo YeniTestDB isimli veritabanında da oluşturulmuş oldu. Ancak yazmış olduğunuz where ifadesi sayesinde mevcut tablodaki verilerin aktarılmasını engellendi.

Eğer buradaki where ifadesi kaldırılırsa bu kez verileriyle birlikte Filmler isimli tablo, YeniTestDB isimli veritabanında oluşturulmuş olacaktı.

Birden Fazla Tablodaki Count(*) Değerinin Toplamına Ulaşmak – UNION vs UNION ALL

Geçen gün projelerin birinde bu tip bir sorguya ihtiyacım olmuştu. Sql’de çok tecrübeli olmadığımdan olaya temkinli yaklaşıp aşağıdaki sorguyu yazmıştım:


SELECT SUM(val) FROM (
SELECT COUNT(*) AS val FROM Tablo1
UNION
SELECT COUNT(*) AS val FROM Tablo2
)

Sorguyu çalıştırıp yanlış değer döndüğünü farkedince olayın UNION kullanmamdan kaynakladığını öğrendim. Temkinli olmak yetmemiş, bilgiye ihtiyacım varmış. Zira UNION farklı değerlerle ilgilenip , tablolardaki aynı değerleri yeni oluşan tabloya dahil etmiyor. Kısaca Sqldeki DISTINCT gibi çalışıyor diyebiliriz. Sorguyu aşağıdaki şekliyle çalıştırınca istediğim sonucu yani iki tablodaki row sayılarının toplamına ulaşmış oldum. Elbette projedeki select sorguları böyle değildi, ancak olayı anlaşılır kılmak adına böylesi daha uygun olur diye düşündüm.

SELECT SUM(val) FROM (
SELECT COUNT(*) AS val FROM Tablo1
UNION ALL
SELECT COUNT(*) AS val FROM Tablo2
)

Şüphesiz bu sonucu sqlde birden fazla yöntemle elde edebiliriz. Sizin de bir çözümünüz varsa paylaşabilirsiniz.