Eki 13, 2014 - Query, X++    1 Yorum

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.

Erkan OĞUZ

Önceki Konu->

<- Sonraki Konu

Benzer yazılar

1 Yorum

  • 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.

Yorum Yazın...