Query Nesneleri Join Yapısı(Inner Join, Outer Join, Exists Join, NotExists Join)
Query nesneleriyle ilgili önceki konularda sorgu oluşturma, range(filitre) yapma konularıyla sıralama ve gruplama konularını iki ayrı bölümde yayınlamıştım. Şimdi ise son olarak bahsedeceğim “Join yapısını” (Inner Join, Outer Join, Exists Join, NotExists Join) sizlere anlatmaya çalışacağım.
Öncelikle Join yapısını kısaca tanımlarsak; Join sayesinde iki farklı tablodaki veriler sırayla ele alınarak ilişkili kayıtları bulmak yerine, tüm ilişkili kayıtları içeren bir veri kümesi oluşturularak bu küme içinde işlem yapılır. Bu sayede o işlem için gereksiz kayıtlara hiç değinilmemiş olur.
Axapta’da bulunan Join yapısı SQL deki aynı mantıkla çalışır. Axapta’daki Select cümleciklerinde kullanılan join lerin aynıları Queryler içinde kullanılmaktadır.
Query kullanırken isteğe veya ihtiyaca göre iki tablo arasında tanımlanmış ilişki(relation) kullanılır veya kendi ilişkinizi oluşturabilirsiniz. Bunun için relation methoduna true değeri göndererek ilişkiyi sağlayabilirsiniz veya false değeri gönderdikten sonra addlink ile kendi ilişkinizi oluşturabilirsiniz.
Sırasıyla Join yapılarını incelemeye başlayalım. Örnek olarak CustTable ve CustTrans tablolarını kullanalım.
CustTable Kayıtları:
AccountNum Name()
MSTR0001 Erkan
MSTR0002 Adem
MSTR0003 Emin
MSTR0004 Mesut
(Bilgi : Axapta 2009 da CustTable üzerinde Name alanı varken Ax2012 de alan kaldırılmıştır. İsimler DirPartyTable üzerinden yönetilmektedir. CustTable üzerinde Name methodu kullanılabilir.)
CustTrans Kayıtları
AccountNum AmountMST
MSTR0001 125
MSTR0002 10
MSTR0002 80
MSTR0002 50
MSTR0004 250
MSTR0004 90
MSTR0001, MSTR0002, MSTR0004 müşterilerinin hareketleri bulunmaktadır. MSTR0003 müşterisinde hareket yoktur.
İnner Join :
En çok kullanılan Join yapısıdır. İlk tablodaki kayıtlar verilen kriterlere göre ikinci tablodaki kayıtlara göre eşleşmesi aranır. Sonucunda ikinci tabloda eşleşmesi bulunmayan kayıtlar ekrana getirilmez. İnner join yapısı için bir “join mode” methodu yazmaya gerek yoktur çünkü varsayılan join tipi Inner joindir.
static void Erkn_QueryJoinOuterJoin(Args _args) { Query q; QueryRun qr; QueryBuildDataSource qbdsCustTable; QueryBuildDataSource qbdsCustTrans; CustTable custTable; CustTrans custTrans; q = new Query(); qbdsCustTable = q.addDataSource(tableNum(CustTable)); //Birinci tablo tanımlanır. qbdsCustTrans = qbdsCustTable.addDataSource(tableNum(CustTrans));//İkinci tablo birinci tabloya ile ilişkilendirilir. qbdsCustTrans.relations(true); //İlişki tablo üzerinden mi kontrol edilecek o belirlenir. //qbdsCustTrans.relations(false); //İlişki manuel olarak belirtilecek. //qbdsCustTrans.addLink(fieldNum(CustTable,AccountNum),fieldNum(CustTrans,AccountNum)); //İki tablo arasındaki ilişki belirtilir. //İkinciDataSourceDeğişkeni.addlink(BirinciTablonun ilişkili alanının FieldIdsi,İkinciTablonun ilişkili alanının FieldIdsi); //qbdsCustTrans.joinMode(JoinMode::InnerJoin); //İlişki tipi belirtilir. Inner Join için gerekli değildir. qr = new QueryRun(q); if(qr.prompt()) { while(qr.next()) { custTable = qr.get(tableNum(CustTable)); custTrans = qr.get(tableNum(CustTrans)); info(strFmt("%1 %2 - %3 %4", custTable.AccountNum, custTable.name(), custTrans.AccountNum, custTrans.AmountMST)); } } }
Sonuç :
AcountNum Name() AcountNum AmountMST
MSTR0001 Erkan MSTR0001 125
MSTR0002 Adem MSTR0002 10
MSTR0002 Adem MSTR0002 80
MSTR0002 Adem MSTR0002 50
MSTR0004 Mesut MSTR0004 250
MSTR0004 Mesut MSTR0004 90
**İkinci tabloda MSTR0003 müşterisi ile ilgili bir hareket bulunmadığı için ekrana getirmedi.
Outer Join :
İlk tablodaki kayıtlar verilen kriterlere göre ikinci tablodaki kayıtlara göre eşleşmesi aranır. Sonucunda ikinci tabloda eşleşmesi bulunan kayıtları listeler, eşleşmesi bulunamayan kaydı ise tek bir satır olarak ekrana getirir ikinci tablodan değer döndürmez.
static void Erkn_QueryJoinInnerJoin(Args _args) { Query q; QueryRun qr; QueryBuildDataSource qbdsCustTable; QueryBuildDataSource qbdsCustTrans; CustTable custTable; CustTrans custTrans; q = new Query(); qbdsCustTable = q.addDataSource(tableNum(CustTable)); //Birinci tablo tanımlanır. qbdsCustTrans = qbdsCustTable.addDataSource(tableNum(CustTrans));//İkinci tablo birinci tabloya ile ilişkilendirilir. qbdsCustTrans.relations(true); //İlişki tablo üzerinden mi kontrol edilecek o belirlenir. //qbdsCustTrans.relations(false); //İlişki manuel olarak belirtilecek. //qbdsCustTrans.addLink(fieldNum(CustTable,AccountNum),fieldNum(CustTrans,AccountNum)); //İki tablo arasındaki ilişki belirtilir. //İkinciDataSourceDeğişkeni.addlink(BirinciTablonun ilişkili alanının FieldIdsi,İkinciTablonun ilişkili alanının FieldIdsi); qbdsCustTrans.joinMode(JoinMode::OuterJoin); //İlişki tipi belirtilir. qr = new QueryRun(q); if(qr.prompt()) { while(qr.next()) { custTable = qr.get(tableNum(CustTable)); custTrans = qr.get(tableNum(CustTrans)); info(strFmt("%1 %2 - %3 %4", custTable.AccountNum, custTable.name(), custTrans.AccountNum, custTrans.AmountMST)); } } }
Sonuç :
AcountNum Name() AcountNum AmountMST
MSTR0001 Erkan MSTR0001 125
MSTR0002 Adem MSTR0002 10
MSTR0002 Adem MSTR0002 80
MSTR0002 Adem MSTR0002 50
MSTR0003 Emin
MSTR0004 Mesut MSTR0004 250
MSTR0004 Mesut MSTR0004 90
**İkinci tabloda MSTR0003 müşterisi ile ilgili bir hareket bulunmadığı için ekrana tek satır olarak getirdi.
Exists Join :
Bu join yapısı ile ikinci tabloda birinci tablodaki değerlerin “varlığını” kontrol eder sonuçları birinci tablodan tek satır olarak döndürür. İkinci tablodan değer döndürmez.
</span> <pre>static void Erkn_QueryJoinExistsJoin(Args _args) { Query q; QueryRun qr; QueryBuildDataSource qbdsCustTable; QueryBuildDataSource qbdsCustTrans; CustTable custTable; CustTrans custTrans; q = new Query(); qbdsCustTable = q.addDataSource(tableNum(CustTable)); //Birinci tablo tanımlanır. qbdsCustTrans = qbdsCustTable.addDataSource(tableNum(CustTrans));//İkinci tablo birinci tabloya ile ilişkilendirilir. qbdsCustTrans.relations(true); //İlişki tablo üzerinden mi kontrol edilecek o belirlenir. //qbdsCustTrans.relations(false); //İlişki manuel olarak belirtilecek. //qbdsCustTrans.addLink(fieldNum(CustTable,AccountNum),fieldNum(CustTrans,AccountNum)); //İki tablo arasındaki ilişki belirtilir. //İkinciDataSourceDeğişkeni.addlink(BirinciTablonun ilişkili alanının FieldIdsi,İkinciTablonun ilişkili alanının FieldIdsi); qbdsCustTrans.joinMode(JoinMode::ExistsJoin); //İlişki tipi belirtilir. qr = new QueryRun(q); if(qr.prompt()) { while(qr.next()) { custTable = qr.get(tableNum(CustTable)); custTrans = qr.get(tableNum(CustTrans)); info(strFmt("%1 %2 - %3 %4", custTable.AccountNum, custTable.name(), custTrans.AccountNum, custTrans.AmountMST)); } } }
Sonuç :
AcountNum Name() AcountNum AmountMST
MSTR0001 Erkan
MSTR0002 Adem
MSTR0004 Mesut
**İkinci tabloda MSTR0003 müşterisi ile ilgili bir hareket bulunmadığı için ekrana getirmedi. İkinci tablodan bir değer döndürmedi.
NotExists Join :
Bu join yapısı exists joinin tersi gibi çalışır. Yine İkinci tabloda birinci tablodaki değerlerin varlığını kontrol eder. Ancak var olmayan kayıtları döndürür.
static void Erkn_QueryJoinNotExistsJoin(Args _args) { Query q; QueryRun qr; QueryBuildDataSource qbdsCustTable; QueryBuildDataSource qbdsCustTrans; CustTable custTable; CustTrans custTrans; q = new Query(); qbdsCustTable = q.addDataSource(tableNum(CustTable)); //Birinci tablo tanımlanır. qbdsCustTrans = qbdsCustTable.addDataSource(tableNum(CustTrans));//İkinci tablo birinci tabloya ile ilişkilendirilir. qbdsCustTrans.relations(true); //İlişki tablo üzerinden mi kontrol edilecek o belirlenir. //qbdsCustTrans.relations(false); //İlişki manuel olarak belirtilecek. //qbdsCustTrans.addLink(fieldNum(CustTable,AccountNum),fieldNum(CustTrans,AccountNum)); //İki tablo arasındaki ilişki belirtilir. //İkinciDataSourceDeğişkeni.addlink(BirinciTablonun ilişkili alanının FieldIdsi,İkinciTablonun ilişkili alanının FieldIdsi); qbdsCustTrans.joinMode(JoinMode::NoExistsJoin); //İlişki tipi belirtilir. qr = new QueryRun(q); if(qr.prompt()) { while(qr.next()) { custTable = qr.get(tableNum(CustTable)); custTrans = qr.get(tableNum(CustTrans)); info(strFmt("%1 %2 - %3 %4", custTable.AccountNum, custTable.name(), custTrans.AccountNum, custTrans.AmountMST)); } } }
Sonuç :
AcountNum Name() AcountNum AmountMST
MSTR0003 Emin
**İkinci tabloda MSTR0003 müşterisi ile ilgili bir hareket bulunmadığı için sadece o kaydı ekrana listeledi.
Merhaba Erkan Bey,
Bir konuda yardımınızı rica edeceğim.
InventOnhandItem (Eldeki) formu üzerine EcoresProduct üzerinden bir alanı getirmek istiyorum.
Bunun için formun datasource una EcoresProduct formuu ekleyip inventTable ile innerjoin yaptım fakat kayıtlar gelmiyor.Neyi gözden kaçırıyorum, şimdiden cevabınız için teşekkürler.