Linq, GROUP ve group_concat

NHibernate hayatıma girdiğinden beri neredeyse heryerde artık Linq kullanıyorum. Büyük kolaylık. Bir çok işlem kısa bir Linq sorgusu ile halledilebiliyor. Özellikle gruplama işlemleri çok kolay. MySql kullandığım zamanlarda group_concat işlemi çok sıkça kullanıyorduk. Örneğin bir hastaya ait bütün gelişleri yada bir örnek numarasına ait bütün testleri görüntülemek için group_concat oldukça kullanışlı oluyordu.

Ehhh tabi ki NHibernate kullanana kadar. Aslında gene group_concat kullanılabiliyor fakat standart olmadığı için diğer veritabanlarında kullanılamıyor.

Neyse şimdi örnek bir linq sorgusunda bu işlem nasıl yapılıyor bir bakalım.
Kullandığım Sql sorgusu aşağıda. Sorgu sonucunu DataTable olarak sonucListesi içerisine attım.

select
ornek.ornek_id,
ornek.ornek_adi,
ornek.ornek_soyadi,
test.test_id,
test.test_adi
from ornek
inner join sonuc on sonuc.sonuc_ornekno = ornek.ornek_id
inner join test on test.test_id = sonuc.test_id
group by
ornek.ornek_id,
ornek.ornek_adi,
ornek.ornek_soyadi,
test.test_id,
test.test_adi
order by
ornek.ornek_adi,
ornek.ornek_soyadi,
test.test_adi

Sql sorgusundan dönen cevap aşağıda CSV olarak verdim.

1000683;ABDULLAH;ABDULLAH_1000683;341;DELTA ANTİKORU
1000490;ABDÜLVAHİT;ABDÜLVAHİT_1000490;1032;HBV DNA (KANTİTATİF) (VİRAL YÜK)
999981;ADNAN;ADNAN_999981;1032;HBV DNA (KANTİTATİF) (VİRAL YÜK)
999778;AHMET;AHMET_999778;188;T3 TOTAL (TT3)
999778;AHMET;AHMET_999778;189;T4 TOTAL (TT4)
999766;AHMET;AHMET_999766;188;T3 TOTAL (TT3)
999766;AHMET;AHMET_999766;189;T4 TOTAL (TT4)
999766;AHMET;AHMET_999766;187;TOTAL LİPİD
1000624;AHMET;AHMET_1000624;176;SERULOPLAZMİN
999775;AHMET;AHMET_999775;181;SİSTİN (24 saatlik idrar )
999775;AHMET;AHMET_999775;183;SPESİFİK IgE (5li miks)
1000386;AHMET;AHMET_1000386;1880;ANTİ - Sm/RNP (immunoblotting)
1000386;AHMET;AHMET_1000386;311;ANTİ NÜKLEER ANTİKOR (ANA)
1000386;AHMET;AHMET_1000386;324;ANTİ-SS-A (ANTİ - Ro ANTİKORU)
1000386;AHMET;AHMET_1000386;325;ANTİ-SS-B (ANTİ - La ANTİKORU)
1000337;Ahmet;Ahmet_1000337;54;CA 125
1000337;Ahmet;Ahmet_1000337;55;CA 15-3
1000337;Ahmet;Ahmet_1000337;56;CA 19-9
1000337;Ahmet;Ahmet_1000337;123;CEA (Karsinoembriyonik Antijen)
1000435;AHMET;AHMET_1000435;369;KİST HİDATİK (IHA)
1000200;AHMET;AHMET_1000200;253;VON WILLEBRANT FAKTÖR ANTİJENİ (VWF)
1000538;AHMET;AHMET_1000538;7;VİTAMİN D (25-HİDROKSİ)
1000510;AHMET;AHMET_1000510;1032;HBV DNA (KANTİTATİF) (VİRAL YÜK)
999772;AHMET;AHMET_999772;186;IgE TOTAL
999772;AHMET;AHMET_999772;185;TG ( TİROGLOBULİN )
1000315;AHMET EMİR;AHMET EMİR_1000315;186;IgE TOTAL
999449;AHSEN;AHSEN_999449;311;ANTİ NÜKLEER ANTİKOR (ANA)
999450;AHSEN;AHSEN_999450;311;ANTİ NÜKLEER ANTİKOR (ANA)
999555;AHSEN;AHSEN_999555;311;ANTİ NÜKLEER ANTİKOR (ANA)
999557;AHSEN;AHSEN_999557;311;ANTİ NÜKLEER ANTİKOR (ANA)
999449;AHSEN;AHSEN_999449;1032;HBV DNA (KANTİTATİF) (VİRAL YÜK)
999450;AHSEN;AHSEN_999450;1032;HBV DNA (KANTİTATİF) (VİRAL YÜK)
999555;AHSEN;AHSEN_999555;1032;HBV DNA (KANTİTATİF) (VİRAL YÜK)
999557;AHSEN;AHSEN_999557;1032;HBV DNA (KANTİTATİF) (VİRAL YÜK)

var sonuc = (from element in sonucListesi.AsEnumerable()
group new { Test = element["test_adi"] } by
new
{
Adi = element["ornek_adi"],
Soyadi = element["ornek_soyadi"],
OrnekId = element["ornek_id"]
}
into groupedData
select new
{
groupedData.Key.Adi,
groupedData.Key.Soyadi,
groupedData.Key.OrnekId,
Testler = string.Join(", ", groupedData.Select(x => x.Test).ToArray())
}).ToList();

Bu kodumuz bize hastalarımıza ait olan testleri göstermektedir. Şimdi biraz inceliyelim.
3.  sonucListesi nesnesi DataTable.
4. anonymous class oluşturup DataTable içerisinde ki test_adi nesnemizi Test field’ine atıyoruz. Bunu yapmamızın nedeni gruplama yaptıktan sonra o nesneye ulaşmak istememizden dolayı.
5-11. burada sql sorgumuzda group by kısmında yazdığımız sütun(column) bilgimiz.
12. gruplamış olduğumuz verileri bir nesne içerisine atıp sonradan seçim kısmında kullanmamızı sağlıyor.
15-19. bu satırlar da ise gruplamış olduğumuz verileri artık bir nesneye atama işlemiş yapıp kullanmamızı sağlıyor. Daha açık olarak şöyle söyliyeyim “select columns from xxx” kısmında ki columns ile belirttiğim sütunları kullanmamızı nasıl sağlıyorsa burada da 15-19 satırlarında seçtiklerimize erişmemizi sağlıyor. Burada dikkat etmeniz gereken birkaç şey var. 12. satırda belirttiğimiz groupedData nesnesinin Key property’ine erişip onun içerinde grupladığımız bilgilerimizi kullanıyoruz. Birde asıl önemli olan kısım Test bilgilerinin gruplanmış olarak alıyoruz. select fonksiyonu ile 4. satırda belirttiğimiz fieldlere erişip işlem yapabiliyoruz. Ben orada string.join ile dizi olarak aldığım bütün testleri virgül koyarak birleştirdim.

Evet son olarak ekran çıktısı aşağıda ki gibi
linq_groupingLinq kullanmadan döngüleri kullanarak ta aynı işlemi gerçekleştirebilirdik. Fakat o işlem de hem çok daha fazla kod yazacaktık hemde işlem biraz daha karışık ve okunması daha zor olacaktık.
İlk başta linq sorgumuzda bu şekilde karışık ve anlamsız olarak görünebilir fakat bir kaç farklı işlemde kullandığınız zaman çok seveceğinizden eminim. Zaten Sql’e olan benzerliğinden dolayı artı puan kazanıyor.
Not: NHibernate ile kullanırken bazen sorun çıkartabiliyor. 

 

Facebook Comments

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir