Merhaba, T-SQL'de yer alan Distinct fonksiyonu ve Group By
clause'unu birçok defa kullanmışızdır, ne iş yaptıklarıda malum yinede
şurdan buradan bakılabilir,
Dönelim konumuza sorun şuki DataTable'e çekilen veriler üzerinde bu
fonksiyonları uygulamak hazır fonksiyonlarlar mümkündeğil ve .Net
Framework ne yazıkki bu konuda hazır bir fonksiyon içermediği için iş
başa düştü, kendi faonksiyonumu hazdım buraya ekliyorum,
kullanabilirsiniz
Şimdi bu fonksiyon ne iş yapar; Diyelimki
veritabanından verilerimizi çekmişiz ama öyle bir select sorgusuyla
değil, iç içe sorgular, fonksiyonlar, hesaplamalarla çekmişiz. Bu titiz
çalışmanın sonucu elimizde sadece bir tablo var fekat biz bu tablo
üzerinde bir daha çalışmak istiyoruz. Örneğin verileri bir daha
gruplamak istiyoruz fakat bunu T-SQL ile yapamıyoruz çünkü yazdığımız
sorgu buna izin vermiyor. Çok abartı bir örnek oldu değilmi, yok yok
hiçte öyle olmadı,değil çünkü, aynı böyle bir durumla karşılaştım bugün
ve oturdum böyle bir fonksiyon yazdım.
public class
SharpSql
{
public
SharpSql(){}
public DataTable Distinct(DataTable dataSource,
string
distinctColumn)
{
DataTable returnTable=new DataTable("distinctTable");
/*
* kaynak tablodaki
sütunları
* geri dönecek tabloya kopyalıyorum
* böylece direkt satır eklenirken
* sütunların
birebir eşleşmesini sağlıyorum
*/
foreach(DataColumn c in dataSource.Columns)
{
returnTable.Columns.Add(c.ColumnName,c.DataType);
}
bool hasRow=false;
foreach(DataRow selectedRow in
dataSource.Rows)
{
/*
* kaynak tabloda herbir satırı seçip
* sonuçların bulunduğu tabloda benzerinin
* olup olmadığına bakıyorum
*/
foreach(DataRow r in returnTable.Rows)
{
/*
*
eşleşen sonuçlar bulunursa,
* satırın var olduğu
anlamında
* hasRow=true yapıyorum
*/
if(r[distinctColumn].ToString() ==
selectedRow[distinctColumn].ToString())
{
hasRow=true;
break;
}
}
/*
* Seçili satır bulunmamışsa hasRow değeri
* varsayılan olarak false olacağı için,
*
satır ekleniyor
*/
if(hasRow==false)
returnTable.Rows.Add(selectedRow.ItemArray);
hasRow=false;
}
return
returnTable;
}
/*
*
her bir sütunun kendi toplamına ihtiyacım vardı
* ve normal
DataColumn'da böyle bir değer yoktu
* bir class oluşturup
inherit ettikten sonra
* Toplam property'sini ekledim
*/
public class GroupColumn:System.Data.DataColumn
{
private double dblToplam;
public GroupColumn(string columnName)
{ this.ColumnName=columnName; }
public double
Toplam
{
get{return dblToplam;}
set{dblToplam=value;}
}
}
/*
* ve yine tip dönüşümlerinde normal DataColumnCollection,
* inherits edilmiş GroupColumn classında
* tip dönüşüm
hatası verdiğinden bunun yerine
* kendi
GroupColumnCollections'ımı yazdım
*/
public class GroupColumnCollection:CollectionBase
{
public
GroupColumnCollection(){}
public
void Add(GroupColumn obj)
{ this.InnerList.Add(obj);}
}
public DataTable
GroupBy(DataTable dataSource,
GroupColumnCollection columns,
string groupByColumn)
{
/*
* Gruplanırken, unique
kolonlara göre
* istenilen toplamlar alınıyor
* Unique(benzersiz) sütunlar yazdığım
* Distinct
fonksiyonu ile eldeediliyor
*/
DataTable
tableDistinct;
tableDistinct=this.Distinct(dataSource,groupByColumn);
/*
* dataview
kullanılıyorki her bir
* groubBy kolonuna göre
* ayrı ayrı sonuçlar alınsın diye
*/
DataView
viewResult=new DataView();
viewResult.Table=dataSource;
DataTable returnTable=new DataTable("groupTable");
DataRow returnRow;
//Sütünlar
ekleniyor
foreach(GroupColumn
c in columns)
{
returnTable.Columns.Add(c.ColumnName,c.DataType);
}
//Adet sütünü
ekleniyor
returnTable.Columns.Add("Adet");
//Gruplamada
kullanılan sütunu ekliyorum
returnTable.Columns.Add(groupByColumn);
//Toplamları hesaplayp ekliyorum
foreach(DataRow r in tableDistinct.Rows)
{
viewResult.RowFilter =groupByColumn + " = '"
+
r[groupByColumn].ToString() + "'";
//Yeni bir satır oluşturuyorum
returnRow = returnTable.NewRow();
/*
* dataviewe rowfilter
uygulandıktan sonra
* kalan satırlar geziliyor ve
* toplamları hesaplayıp
* değerleri yeni
satıra atıyorum
*/
for(int
i=0;
i<=viewResult.Count;
i++)
{
foreach(GroupColumn
c in columns)
{
c.Toplam +=
Convert.ToDouble(viewResult[i][c.ColumnName]);
returnRow[c.ColumnName]=c.Toplam;
}
}
//Grup adı ve adetini ekliyorum
returnRow[groupByColumn]=r[groupByColumn].ToString();
returnRow["Adet"]=viewResult.Count;
//Son olarak satırı tabloya
ekliyorum
returnTable.Rows.Add(returnRow);
}
return
returnTable;
}
}
Bu kadar
yazdıktan sonra hadi ne haliniz varsa görün demiycem elbette, şimdi bunu
örnek bir uygulamada kullanarak ne işe yaradığını tam olarak anlatayım,
Yeni bir WindowsApplication projesi açıp, yukardaki Classımızı orya
ekliyelim, ardında forma 2 DataGrid 3 adette button ekleyip aşşağıdaki
kodları yazıyoruz,
/
/yukardaki classtan bir instance oluşturuyorum
SharpSql
csSql=new SharpSql();
//verileri getir butonu
private void
button1_Click(object sender,
System.EventArgs e)
{
SqlConnection cn=new SqlConnection(
"Data Source=.;
Initial Catalog=Northwind;
Integrated Security=SSPI;");
SqlCommand
cmd=new SqlCommand("select * from [Order Details]",cn);
SqlDataAdapter da=new
SqlDataAdapter(cmd);
DataSet ds=new
DataSet();
da.Fill(ds,"siparisDetay");
dataGrid1.DataSource=ds.Tables[0];
}
//Distinct butonu
private
void button2_Click(object sender, System.EventArgs e)
{
/*
* tekrar eden kayıtlar
eleniyor
* ve
sonuç bir DataTable olarak döndüğü için
* DataSet'e ekliyorum
*/
string
distinctColumn;
distinctColumn=((DataTable)dataGrid1.DataSource).Columns[dataGrid1.CurrentCell.ColumnNumber].ColumnName
;
dataGrid2.DataSource=csSql.Distinct((DataTable)dataGrid1.DataSource
,distinctColumn);
}
//Group By
butonu
private void button3_Click(object sender, System.EventArgs e)
{
/*
* Gruplandırmada kullanılacak
sütun ve
* toplamların alınacağı sütunları ekliyorum
*
sonuç yine datatable olarak döndüğünden
* onuda dataset'e
ekliyorum
*/
SharpSql.GroupColumnCollection col=new SharpSql.GroupColumnCollection();
SharpSql.GroupColumn obj;
obj=new
SharpSql.GroupColumn("UnitPrice");
col.Add(obj);
obj=new
SharpSql.GroupColumn("Quantity");
col.Add(obj);
string
groupColumn;
groupColumn=((DataTable)dataGrid1.DataSource).Columns[dataGrid1.CurrentCell.ColumnNumber].ColumnName;
dataGrid2.DataSource=csSql.GroupBy((DataTable)dataGrid1.DataSource,col,groupColumn);
}
Programı
çalıştırdığımızda öncelikle Verileri Getir butonunu tıklıyoruz gelen
veriler sadece select sorgumusun sonuçları, ProductID sütununa göre
sıralayınca anlaşılacaktır zaten, ProductID stünunu seçip Distinct
butonuna tıklayınca sonuçlar dataGrid2'de görünecektir tekrar edilen
satırlar elendi
Group By butonuna tıladığımızda ise bu defata, kodlarımızda
belirttiğimiz Quantity ve UnitPrice sütunlarındaki değerlerin
ProductID'ye göre toplamları görünecektir
Benimde en çok ihtiyaç duyduğum kısım
GroupBy kısmıydı ve bu işimi oldukça gördü umarım sizlerinde işine yarar
(biraz uzun oldu sanki

)