Kur Tablosu Üzerinden FILTER, VALUES ve MAX

Power Query 'de liste oluşturma ve merge yapma işlemleri için daha önceki yazıda kur tablosu örneğini vermiştim. Özetlemek gerekirse, farklı para birimleri üzerinden satış satırlarımız ve belirli tarih aralıkları için geçerli bir kur tablomuz vardı.


Satışların olduğu tabloya, ilgili satırdaki kurun ilgili tarihteki kurunu getirip aşağıdaki forma sokmuştuk.


Aynı örneği bir de DAX ile yapalım.

Aşağıdaki formülü bir  hesaplanmış sütun  olarak satışlar tablosuna ekliyorum:

Kur = 
CALCULATE ( MAX (Kurlar[Kur]);
    FILTER ('Kurlar';
        'Satışlar'[Para Birimi] = 'Kurlar'[Para Birimi] &&
        'Satışlar'[Tarih] <= 'Kurlar'[Bitiş Tarihi] &&
        'Satışlar'[Tarih] >= 'Kurlar'[Başlangıç Tarihi]
    )
)


İki tablo arasında herhangi bir ilişki yok, ama gene de her iki tablodan da eşlenik olan kayıtları bulabiliyoruz!

Yazdığımız hesaplanmış sütun  row context yaratıyor , yani satışlar tablosunun her bir satırı için çalışacak.  FILTER ('Kurlar'…)  kodu da  row context yaratıyor , çünkü FILTER bir iterator.

Satışlar tablosunun her bir satırı için,  Kurlar tablosundaki tüm satırları, para birimi aynı olacak ve satış tarihi kur tablosundaki başlangıç ve bitiş tarihleri arasında olacak şekilde tarayacak ve filtreleyecek! Tüm koşulları && (AND) operatörü ile birleştirdik.

Bu örnekte,  MAX (Kurlar[Kur])  yerine SUM, AVERAGE, MİN 'de kullanabilirdim, aynı sonucu döndürecektir, çünkü her bir tarihte ilgili kur için  tek satır döneceğini  biliyoruz.

Benzer bir ihtiyacın olduğu başka örneklerde FILTER sonucunda dönen tabloda birden fazla satır olması durumunda dönen değerleri  ne yapmak istiyorsanız ona göre uygun fonksiyonu kullanmak gerekir. Ama yukarıdaki örnek için farketmeyecektir.

Kurlar tablosunda TL olmadığı için boş geliyor, TL satırı için kur değeri 1 olacak şekilde formülümüzü modifiye edelim:

Kur Modifiye = 
IF ('Satışlar'[Para Birimi] = "TL";
    1;
    CALCULATE ( MAX (Kurlar[Kur]);
        FILTER ('Kurlar';
            'Satışlar'[Para Birimi] = 'Kurlar'[Para Birimi] &&
            'Satışlar'[Tarih] <= 'Kurlar'[Bitiş Tarihi] &&
            'Satışlar'[Tarih] >= 'Kurlar'[Başlangıç Tarihi]
        )
    )
)


Satışlar formülümüzü artık yazabiliriz:

Satışlar := SUMX ('Satışlar';'Satışlar'[Satış Tutarı] * 'Satışlar'[Kur Modifiye])

DAX'ta row context yaratan iki tane konsept vardır: hesaplanmış sütunlar ve iterator fonksiyonlar. Bu cümleyi de son kez kurmuş olayım ve devam edeyim.

Aynı durumu hesaplanmış sütun yerine  metrik yazarak  nasıl yapabiliriz?

Hesaplanmış sütun olarak yazdığımız formülü acaba metrik olarak yazsak çalışır mı?


Çalışmıyor!

Resme dikkat ederseniz, hata mesajıyla birlikte satışlar tablosundan gelen sütunların altını kırmızı çizgiyle işaretledi. Ama kurlar tablosundan gelen sütunların altında herhangi bir işaret yok!

Bunun anlamı şu,  FILTER ('Kurlar' …)  kodu bir row context yarattığından, yani satır bazlı çalıştığından, Kurlar tablosundaki satırların her birinin tek tek farkında ve sütun değerlerini doğrudan görebiliyor.

Fakat  CALCULATE ( MAX …)  artık bir hesaplanmış sütun değil, bir metrik, dolayısıyla satışlar tablosundaki satırların farkında değil. Satışlar tablosunu görebiliyor ama satır bazında değil, sütun veya tablo bazında görüyor! Satış tablosundaki satırların farkında olmadığı için de bu tablodan doğrudan sütun ismi vererek bir değer çağırmamıza müsade etmiyor.

Satırların sütun değerlerini görebilmesi için birden fazla fonksiyon kullanabiliriz: MAX, MIN, LASTNONBLANK, VALUES gibi.

VALUES ile bir deneme daha yapalım:  VALUES (Sütun Adı) , verdiğimiz sütundaki tekil değerleri -blank dahil- tek sütunluk bir tablo olarak döndüren bir fonksiyon.

Formülü yazdık, herhangi bir hata mesajı yok!

Önceki matrise yazdığımız metriği düşürüyorum:

Formülü yazarken hata vermedi ama matrise  düşürünce "gösteremiyorum" diyor. Detayına bakınca şu mesaj çıkıyor:


Hata mesajı, tek bir değer beklerken, birden fazla değerin geldiğini söylüyor! VALUES ile ilgili en sık rastlanan hata mesajı bu.

Formüldeki  VALUES('Satışlar'[Para Birimi])  ve  VALUES('Satışlar'[Tarih]) , matristeki tekil satırlar için tek değer döndürüyor: satırdaki para birimi ve tarih neyse onlar. Fakat toplam satırı için döndürdüğü listede birden fazla değer var, yani satışlar tablosundaki tekil para birimlerini ve satış tarihlerini görüyor. Gördüğü değerlerden hangilerini kurlar tablosundaki satırlarla karşılaştıracak? Bilmiyor!

Sorun yaratan sadece toplam satırı için birden fazla değer dönmesi. Eğer formülü matristeki sadece tekil satırlar için çalışacak şekilde modifiye edersek çalışacaktır.

Kur Metrik := 
CALCULATE ( MAX (Kurlar[Kur]);
    FILTER ('Kurlar';
        IF (HASONEVALUE('Satışlar'[Para Birimi]);
            VALUES('Satışlar'[Para Birimi]) = 'Kurlar'[Para Birimi] &&
            VALUES('Satışlar'[Tarih]) >= 'Kurlar'[Başlangıç Tarihi] &&
            VALUES('Satışlar'[Tarih]) <= 'Kurlar'[Bitiş Tarihi]
        )
    )
)


Satırda mıyız yoksa toplam satırında mıyız bilgisini IF ( HASONEVALUE …) kalıbı ile daha önce de yapmıştık.

TL satırı için metriğimizi modifiye edelim:

Kur Metrik Modifiye := 
IF ( HASONEVALUE ('Satışlar'[Kur]) && VALUES ('Satışlar'[Para Birimi]) = "TL";
    1;
    CALCULATE ( MAX (Kurlar[Kur]);
        FILTER ('Kurlar';
            IF (HASONEVALUE('Satışlar'[Para Birimi]);
                VALUES('Satışlar'[Para Birimi]) = 'Kurlar'[Para Birimi] &&
                VALUES('Satışlar'[Tarih]) >= 'Kurlar'[Başlangıç Tarihi] &&
                VALUES('Satışlar'[Tarih]) <= 'Kurlar'[Bitiş Tarihi]
            )
        )
    )
)       


Satışları yeni metriğimizle tekrar yazalım:

Satışlar Kur Metriği İle := SUMX ('Satışlar'; 'Satışlar'[Satış Tutarı] * [Kur Metrik Modifiye])

Kur metriğini MAX, LASTNONBLANK gibi fonksiyonlarla da bulmak mümkün.

Kur Metrik MAX := 
CALCULATE (MAX(Kurlar[Kur]);
    FILTER ('Kurlar';
        MAX('Satışlar'[Para Birimi]) = 'Kurlar'[Para Birimi] &&
        MAX('Satışlar'[Tarih]) >= 'Kurlar'[Başlangıç Tarihi] &&
        MAX('Satışlar'[Tarih]) <= 'Kurlar'[Bitiş Tarihi]
    )
)

Hangi yöntemi önerdiğime gelince; Power Query ile yaptığımız yöntemi önereceğim. Kur tablosunda her bir gün için 3 farklı kur olsa 3 yıllık bir periyod için en fazla 3×365 satırla işlem yaparız. Yazıdaki DAX formülleri evet çalışıyor, ama satışlar tablomuz 100 milyon satırsa, her bir satır için iterasyon yapıyoruz, hissedilir bir hız farkı olmayacaktır belki ama Power Query ile her bir ardışık gün için tabloya kur değeri getirmeyi daha elegan bir çözüm olarak değerlendiriyorum.

Seçim sizin.

Yazıdaki modeli indirebilirsiniz

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