RANKX fonksiyonuna daha önceki EARLIER yazısında bir giriş yapmıştık. Fonksiyonu hem hesaplanmış sütun hem de metrik olarak örneklendireceğim, zira gelen soruların büyük bir kısmı bu iki konsept arasındaki farkların biraz daha açılması gerektiğini gösteriyor. Bu yüzden muhtemelen bir ikinci yazı daha yazacağım RANKX ile ilgili ve muhtemelen her iki yazı da normalden uzun olacak, baştan söylemiş olayım!
RANKX, sıralama yapmak amacıyla kullanabileceğimiz bir fonksiyon, sonundaki X’ten anlaşılacağı üzere bir iterator. Her iterator gibi bizden çalışmak için bir tablo ve bu tabloda gördüğü satırlar üzerinde çalıştıracağı deyimi istiyor.
Yazım şekli ve opsiyonları tam olarak şöyle:
RANKX ( tablo ; deyim ; değer ; sıralama şekli ; eşitlik durumunda sıralama nasıl olacak )
Tablo ve deyim zorunlu, diğerleri parametreler ise opsiyonel. Opsiyonel parametrelerden “değer” olanı biraz kafa karıştırıyor, bu yüzden yazıların en sonunda bu parametreye değineceğim. Diğer opsiyonel parametreler ise kolay, büyükten küçüğe doğru mu sıralayacağız yoksa küçükten büyüğe mi, aynı en yüksek değere sahip -diyelim- 5 tane ürün varsa sıralama 1-2-3 diye mi gitsin yoksa 1-6-7 diye mi gibi ayarları yapmamızı sağlıyor.
Her zamanki gibi bir satışlar metriğimiz var.
Satışlar := SUM ('Satışlar'[Tutar])
Ürün kategorilerini satış büyüklüklerine göre sıralamak istiyoruz diyelim.
RANKX’i fonksiyonunu bir metrik olarak yazıyorum ve matrise düşürüyorum.
Kategori Sıralaması HATALI := RANKX ('Ürün Kategorileri' ; [Satışlar] )
Tüm kategoriler için -her bir kategorinin satışları farklı olmasına rağmen- 1 gösteriyor!
RANKX’i bir metrik olarak kullanmak istediğimizde -konseptlerle düşünmediğimizde- ilk yaptığımız hata -zamanında ben de dahil olmak üzere- genelde bu!
Metrikler, çalışmak için öncelikle filter context’ini ve varsa devamında row context’ini bulmak zorunda. DAX’ta her hücre -toplam satırı da dahil olmak üzere- tek tek ve ayrı ayrı ilgili context altında hesaplanır.
Ev Aletleri kategorisi için formül hesaplama yaparken filter context’inde sadece “Ev Aletleri” kategorisi var, Bilgisayarlar için hesaplama yaparken gördüğü context’te sadece bilgisayarlar var. Yani satırdaki kategori neyse sadece onu görüyor, diğer kategorileri görmüyor. Bu yüzden her bir kategori için 1 hesaplıyor.
Toplam satırı için gördüğü şey ise tüm kategoriler, bu satır için [Satışlar] metriğinin değeri diğer tüm kategori satışlarından yüksek olduğu için sırasını 1 olarak hesaplıyor.
Sadece satırdaki kategoriyi değil tüm kategorileri görebileceği şekilde context’i değiştirmemiz lazım. ALL ile formülü farklı bir şekilde yazıp matrise düşürüyorum.
Kategori Sıralaması := RANKX ( ALL ('Ürün Kategorileri') ; [Satışlar] )
ALL (‘Ürün Kategorileri’) ile sadece kendisini değil, tüm kategorileri görmesini sağladığımızda doğru çalışıyor.
* Context kavramı için bu, bu ve bu yazılara göz atmak isteyebilirsiniz.
Toplam satırı için bir sıralama yaptırmıyor olmamız lazım, bunu da daha önce kullandığımız HASONEVALUE veya ISFILTERED -veya HASONEFILTER ile- sağlayabiliriz.
Kategori Sıralaması Modifiye :=
IF (
HASONEFILTER ('Ürün Kategorileri'[Kategori]);
RANKX ( ALL ('Ürün Kategorileri') ; [Satışlar])
)
Dilimleyiciden bazı kategorileri seçiyorum.
Metrik bu haliyle tüm kategorileri gördüğü için sıra numaraları değişmedi. Eğer yaptığımız kategori seçimlerine riayet etmesini istiyorsak ALLSELECTED fonksiyonunu kullanmalıyız.
Kategori Sıralaması_ALLSELECTED :=
IF (
HASONEFILTER ('Ürün Kategorileri'[Kategori]);
RANKX ( ALLSELECTED ('Ürün Kategorileri') ; [Satışlar] )
)
ALL ve ALLSELECTED ile ilgili önceki yazıya göz atmak isteyebilirsiniz.
…
RANKX’i bir metrikte kullandığımızda yapabileceğimiz bir hata tipi daha var!
Doğru ve istediğimiz gibi çalışan sıralama metriklerinde dikkat ederseniz [Satışlar] metriğini doğrudan adıyla çağırdık!
RANKX bir iterator, yani row context yaratıyor. DAX’taki önemli konseptlerden biri “context transition” idi. Row context altında çalışırken bir metriği çağırdığımızda (başına CALCULATE yazsak da yazmasak da) context transition gerçekleşir. Satırdaki “şey” neyse (bizim örneğimizde her bir ürün kategorisi) , bunun eşleniği olan filter context bulunur.
Ürün kategorilerini bu sefer satış miktarına göre hesaplamak istiyoruz diyelim: Satışlar tablomuzda bir “Miktar” sütunumuz var, ama bunu toplayan [Satışlar Miktar] gibi bir metrik henüz yazmamışız. Formülün açık halini yazarak RANKX ile birlikte bir metrik olarak yazıyorum.
Miktara Göre Sıralama HATALI :=
IF (
HASONEFILTER ('Ürün Kategorileri'[Kategori] );
RANKX ( ALLSELECTED ('Ürün Kategorileri') ; SUM('Satışlar'[Miktar]))
)
Her bir kategori için -satış miktarları farklı olmasına rağmen- 1 gösteriyor!
RANKX’in iterate ettiği tablonun satırındaki kategori neyse bunun satış miktarını ve tüm seçili kategorilerin satış miktarlarını görebilmemiz lazım. Oysa şu an sadece satırdaki kategorinin satış miktarını görüyor. Bu durumu düzeltmek için yazdığımız açık SUM(…..) formülünün başına CALCULATE eklememiz gerekiyor ki, context transition gerçekleşsin!
Miktara Göre Sıralama DOĞRU :=
IF (
HASONEFILTER ('Ürün Kategorileri'[Kategori] );
RANKX ( ALLSELECTED ('Ürün Kategorileri') ; CALCULATE ( SUM ('Satışlar'[Miktar]))
)
)
Context transition devreye girdiğinde, yani RANKX’in iterate ettiği satırdaki kategoriyi ve diğerlerini görebildiğimizde yazdığımız formül doğru çalışmaya başlıyor.
İki formülün “neyi gördüğünü” anlamak önemli. Bunun için CONCATENATEX fonksiyonu ile iki yeni metrik yazacağım, amaç yukarıdaki iki formülün gördüğü miktar değerlerini bulmak. CONCATENATEX iterator bir fonksiyon (sonunda X var) ve temel amacı aslında string birleştirmek.
Neyi Görüyor 1 :=
IF (
HASONEFILTER ('Ürün Kategorileri'[Kategori] );
CONCATENATEX ( ALLSELECTED ('Ürün Kategorileri') ;
SUM ('Satışlar'[Miktar]) ; "-"
)
)
Neyi Görüyor 2 :=
IF (
HASONEFILTER ('Ürün Kategorileri'[Kategori] );
CONCATENATEX ( ALLSELECTED ('Ürün Kategorileri') ;
CALCULATE ( SUM ('Satışlar'[Miktar])) ; "-"
)
)
Yukarıdaki formüllerde RANKX yerine CONCATENATEX geldi ve – ile değerleri birleştirdik.
Görüldüğü gibi SUM(…) başına CALCULATE eklediğimizde tüm kategorilerin miktarlarını görebiliyor, çıplak yazdığımızda ise sadece satırdaki kategorinin miktarlarını görebiliyor!
…
Şu ana kadar yazdığımız metriklerde RANKX’e tablo olarak ‘Ürün Kategorileri’ tablosunu verdik ama bu tablodaki ‘Kategori’ sütununu da verebiliriz.
Kategori Sıralaması Sütun Vererek :=
IF (
HASONEFILTER ('Ürün Kategorileri'[Kategori]);
RANKX ( ALLSELECTED ('Ürün Kategorileri'[Kategori]) ; [Satışlar])
)
Verdiğim örnek görseller için aynı çalışacaktır ama hatırlamakta fayda var, ALL (Tablo Adı) verdiğimiz tablodaki hiç bir filtreyi umursamaz, ALL (Sütun Adı) ise verdiğimiz sütunu filtreleyen hiç bir şeyi umursamaz. Rapor sayfasına eklediğiniz filtrelere göre farklı tepkiler verebilir.
…
Yazdığımız formüller hep ürün kategorilerinin satış büyüklüğüne göre sıralanması üzerine, dolayısıyla kategori seviyesinde beklediğimiz sıralamayı döndürüyor. Matrise Renk altına Kategorileri düşürüyorum.
Renk satırlarında bir rakam yok, formülümüzdeki HASONEFILTER (‘Ürün Kategorileri'[Kategori]) ‘den dolayı. Ve sıralamalar doğru.
Tersini yapıyorum, yani kategori altına renk sütununu düşürüyorum.
Bir sıralama hesaplıyor! Ama gösterdiği şey ne?
Gösterdiği şey, her bir rengin ilgili kategorideki satış büyüklüğüne göre sıra numarası!
Her ne formülü yazarsak yazalım, “neyi görüyorum” sorusunun cevabını bulmadan hesaplama yapamayız DAX’ta.
…
RANKX’in bize fayda sağlayacağı konulardan biri şu, yüzlerce müşteri binlerce ürün olduğunda bazen hepsini aynı matriste (görselde) görmek istemeyiz, çünkü raporu okumayı zorlaştırır, en büyük 20 müşteriye ya da en kötü 10 ürüne odaklanmak isteriz. Bunu yapmak için RANKX’e ihtiyacımız var.
Bununla ilgili kullanılabilecek yöntemleri bir dahaki yazıya bırakıyorum, zira okunabilir uzunlukta olmaktan çıkacak yazı.
Yazıdaki modeli indirebilirsiniz.
Sadece üyeler görebilir. Hızlı üyelik için sosyal medya hesabınızla giriş yapabilirsiniz!
PowerBı ve DAX ta türkçe kaynak bulmanın halen zor olduğu şu günlerde harika detaylara değinmişsiniz.
Ellerinize sağlık
Son zamanlarda üzerine çokça araştırma yaptığım konu. Bir de sizden okumak öğrendiklerimin üzerine cila oldu 🙂 Bir sonraki yazınızı heyecan ve sabırsızlıkla bekliyorum. Teşekkürler,