Context Transition

DAX 'taki en önemli fonksiyonlardan biri olan CALCULATE 'in sahip olduğu kabiliyetlerden biri de  context transition .

Formal tanımı şu şekilde: CALCULATE, bir row context altında çalışırken, ilgili row context'i eşleniği olan filter context'e çevirir.

Bu ne demek açalım.

Daha önce aggregator ve iterator fonksiyonlara SUM ve SUMX üzerinden giriş yaptığımız yazıda  "Ürünler" tablosuna şöyle bir hesaplanmış sütun eklemiştim:

Hesaplanmış Sütun SUM = SUM ('Satışlar'[Tutar] )

O yazıdaki açıklamaya bir cümle daha ekleyeceğim :

Her satırda aynı değeri, tüm satışları gösteriyor ! Aggregator'lar satır görmezler, sütun görürler . Gördüğü de "Tutar" sütunundaki tüm değerler olduğu için her satır için tüm tutarların toplamını getiriyor.

+

Hesaplanmış sütunda filter context yoktur, sadece row context vardır.

Formülü CALCULATE ile birlikte yazarak değiştiriyorum:

Hesaplanmış Sütun CALCULATE = CALCULATE ( SUM ('Satışlar'[Tutar] ) )


Her bir satır farklı değerleri gösteriyor ve gözüken rakam ilgili satırdaki ürün neyse, bu ürünün toplam satışları!

Cümleyi tekrarlayacağım:

CALCULATE, bir row context altında çalışırken, ilgili row context'i eşleniği olan filter context'e çevirir: Burada row context'i yaratan şey hesaplanmış sütunun kendisi.   Her bir satır için çalışacak : ilk satırdaki row context'teki ürün "842" id'li ürün. Bunu filter context'e çevirdiğinde, modeldeki ilişkiler üzerinden ok yönünde akabildiği her tabloya bu filtreyi uygulayacak.

 Filter context, modeldeki tablolar arasındaki ilişkiler boyunca ok yönünde akar, yani propagate eder .

Ürünler tablosundaki row context'i filter context'e çevirdiğinde, bu context'i ok yönünde satışlar tablosuna taşıyor ve ürünler tablosunda iterate ettiği ilk satır için satışlar tablosuna ürün id = 842 filtresini koyuyor, dolayısıyla gördüğü satırlar, satışlar tablosundaki 842 id'li ürünün olduğu satırlar.

Aynı şeyi ürünler tablosunda iterate ettiği her bir satır için tekrarlıyor. Sonuç olarak ürünler tablosundaki her bir ürün için, ilgili ürünün satışlarını hesaplıyor.

Aslında bu davranışın benzerini daha önceki RELATED ve RELATEDTABLE yazılarında gördük.

Tablolar arası ilişkilerin farkında olmayan hesaplanmış sütunun yarattığı row context'in, aradaki ilişkilerin farkına varabilmesi için RELATEDTABLE ile birlikte kullanmıştık.

Kategori Satışları = SUMX ( RELATEDTABLE ('Satışlar'); 'Satışlar'[Tutar])

Aynı hesabı context transition sayesinde CALCULATE ile de yapabiliriz.

Kategori Satışları CALCULATE = CALCULATE ( SUM ('Satışlar'[Tutar]))


Bu örnekle birlikte context transition'ın nasıl çalıştığı daha iyi anlaşılıyor.

Modelimizde satışları hesaplayan bir metriğimiz halihazırda var:

Satışlar := SUM ('Satışlar'[Tutar])

Kategori satışlarını hesaplayan formülü gene hesaplanmış sütun olarak  bu metriği çağırarak  yazalım:

Kategori Satışları Metrik Çağırarak = CALCULATE ([Satışlar])

Aynı sonuçları alacağız, hesaplanmış sütunun yarattığı row context altında çalışan CALCULATE, bulunduğu satırdaki row context'i Satışlar tablosuna filter context olarak uygulayacak.


Hatta bir hesaplanmış sütun daha ekleyelim kategoriler tablosuna ve bu sefer sadece [Satışlar] metriğini başında CALCULATE olmadan çağıralım.

Kategori Satışları Sadece Metrik = [Satışlar]


Aynı şeyi hesaplıyor!

Yazdığımız herhangi bir formülde,  bir metriği çağırdığımızda, başına CALCULATE eklemesek bile DAX otomatik olarak başında CALCULATE varmış gibi çalıştırır . Yani  CALCULATE ([Satışlar])  ifadesi ile [Satışlar] her zaman aynıdır.

Daha önceki notasyona ilişkin yazıdaki, metrik çağırırken sadece metriğin adını yazın, önüne tablo ismi koymayın, ama sütun çağırırken mutlaka önüne tablo ismini yazın önerisinin gerekçesi de bu: formülde çağırdığımız şeyin ne olduğunu bilmemiz lazım, metrik mi çağırıyoruz, yoksa sütun mu?  Davranış tamamen farklı olacaktır çünkü.

DAX'a giriş yazısında kurduğum bir cümleye atıfta bulunacak bir örnek yapalım : "bir metriği doğrudan çağırmakla, metriğin formülünü sıfırdan yazmak arasında nüans vardır. Her zaman aynı sonuçları vermeyebilir."

Ortalama müşteri satışlarını hesaplayan bir metrik yazalım:

Ortalama Müşteri Satışları := AVERAGEX ('Müşteriler' ; [Satışlar])
[Satışlar] metriğinin başında CALCULATE olmasa da otomatik CALCULATE eklendiğini artık biliyoruz.

 Bu ortalamanın üstündeki  müşteri satışlarını hesaplamaya çalışalım.

Ortalamanın Üstündeki Satışlar := 
SUMX ('Müşteriler';
    IF ([Satışlar] > [Ortalama Müşteri Satışları];
        [Satışlar]; BLANK()
    )
)

SUMX bir iterator, yani row context yaratan bir fonksiyon. Ve bunun altında -başına CALCULATE yazmasak da- metrikler çağırıyoruz: [Satışlar] ve [Ortalama Müşteri Satışları].

Dolayısıyla context transition devreye giriyor: SUMX 'in iterate ettiği satırdaki müşteri kimse, onun satışlarına ve müşteri ortalama satışlarına bakıyoruz!  Her iki metrik de aynı müşteri için aynı sonucu vereceğinden IF condition'da yazdığımız "true" olması durumunda satışları döndür kısmı boş dönüyor.

Metrik çağırdığımızda context transition mutlaka gerçekleşiyor,  bunu engellemek için  [Ortalama Müşteri Satışları] metriğini çağırmak yerine metriğin açık formülünü yazabiliriz!

Ortalamanın Üstündeki Satışlar Expanded := 
SUMX ('Müşteriler';
    IF ([Satışlar] > AVERAGEX ('Müşteriler'; [Satışlar]);
    [Satışlar] ; BLANK()
    )
)


Son olarak değişken kullanımına bir örnek olması adına aynı metriği değişken kullanarak yazalım, değişken kullanımına da bir giriş örneği olsun:

Ortalamanın Üstündeki Satışlar VAR := 
VAR OrtalamaSatislar =
    AVERAGEX ( 'Müşteriler'; [Satışlar] )
RETURN
    SUMX ('Müşteriler';
        IF ( [Satışlar] > OrtalamaSatislar;
             [Satışlar]; BLANK () )
    )

Yazıdaki modeli indirebilirsiniz.

Sadece kayıtlı üyeler görebilir. Giriş veya Üyelik için login.