LASTDATE, FIRSTDATE

LASTDATE hemen her projede en az bir kez ihtiyaç duyabileceğimiz fonksiyonlardan. İsimden tahmin edilebileceği gibi ekürisi de var: FIRSTDATE.

LASTDATE ( 'TabloAdı'[Tarih Sütunu] )  sadece tarih tipindeki sütunlarla çalışır  ve döndürdüğü şey, gördüğü mevcut filter context'teki en son tarihtir. Dönen tarih, tek bir değer dönüyor olsa da bir tablodur,  tek bir sütundan ve tek bir satırdan oluşan bir tablo . Dolayısıyla bizden parametre olarak tablo isteyen başka fonksiyonlarla birlikte kullanılabilir.

Aşağıdaki metrikleri matrise düşürüyorum. İlki Tarih tablosundaki Tarih sütunu, diğeri Satışlar tablosundaki Tarih sütunu üzerinde çalışıyor.

Son Tarih := LASTDATE( 'Tarih'[Tarih] )
Son Tarih_Satışlar := LASTDATE( 'Satışlar'[Tarih] )


Her ikisi de aynı gibi gözükse de aynı değil. 2007 Kasım için ilk metrik 30.11.2007'yi gösterirken ikincisi 29.11.2007'yi gösteriyor.  Tarih tablosunda -olması gerektiği gibi- yıllara ait tüm tarihler var, dolayısıyla ilk metrik her durumda her ayın -her çeyreğin ve her yılın- son tarihini gösterecektir. Satışlar tablosundaki tarih sütununu referans alan metrik ise bu tabloda gördüğü en son tarihi döndürüyor. En son satış Kasım 2007 için 29.11.2007 'de yapılmış.

Dönemsel karşılaştırmalar yaparken matristeki (görseldeki) zaman periyoduna ait ilk ve son tarihleri bilmek bizim başka bir çok metriği yazmamızı kolaylaştıran bir durum.

Time Intelligence grubundaki fonksiyonlarla denemeler yapalım.

 SAMEPERIODLASTYEAR ( 'Tablo'[TarihSütunu]  ya da tek sütunluk tarih bilgisi içeren TabloAdı ) , aynen adından tahmin edilebileceği gibi mevcut context'te gördüğü tarih(ler)in bir yıl öncesini bulmamızı sağlar. LASTDATE'in döndürdüğü "şey" tek sütunluk -ve tek satırlık- bir tablo olduğuna göre birlikte kullanılabilir.

SamePeriodLastYear_LASTDATE := SAMEPERIODLASTYEAR( LASTDATE( 'Tarih'[Tarih] ) )

Bu fonksiyonun da döndürdüğü "şey"  tek sütunluk tarih bilgisi içeren bir tablo .

Dolayısıyla bu da bizden tablo isteyen başka bir fonksiyonla kullanılabilir!

** Ara not: Aynı şeyi DATEADD ile de bulmak mümkün, DATEADD ayrı bir yazı konusu, bu yüzden sadece ön bilgi olarak değerlendirin.

SAMEPERIODLASTYEAR ( Tarih Sütunu ) = DATEADD ( Tarih Sütunu ; -1 ; YEAR )

Bir gün sonrasının tarihini bulalım:

NextDay_SamePeriodLastYear_LASTDATE := NEXTDAY( SAMEPERIODLASTYEAR( LASTDATE( 'Tarih'[Tarih] ) ) )


Daha işe yarar bir metrik yazmanın zamanı geldi:  Matristeki zaman periyodunun son tarihini ve bir yıl önceki tarihi görebildiğimize göre son bir yıllık yürüyen toplam satışları bulabiliriz (moving annual total). İki tarih arasındaki değerleri bulmamızı sağlayacak DATESBETWEEN fonksiyonunu kullanalım. Syntax'ı basit:

DATESBETWEEN ( TarihSütunu ; BaşlangıçTarihi ; BitişTarihi )
Son 1 Yıllık Yürüyen Satışlar := 
CALCULATE( [Satışlar] ;
      DATESBETWEEN( 'Tarih'[Tarih] ;
            NEXTDAY( SAMEPERIODLASTYEAR( LASTDATE( 'Tarih'[Tarih] ) ) ) ;
            LASTDATE( 'Tarih'[Tarih] )
      )
)


Son 1 yılın ortalama satış büyüklüğünü bulmak istersek bunu da kolaylıkla yapabiliriz.

Son 1 Yıllık Yürüyen Ortalama Satış Büyüklüğü := 
CALCULATE( AVERAGE( 'Satışlar'[Tutar] ) ;
      DATESBETWEEN( 'Tarih'[Tarih] ;
            NEXTDAY( SAMEPERIODLASTYEAR( LASTDATE( 'Tarih'[Tarih] ) ) ) ;
            LASTDATE( 'Tarih'[Tarih] )
      )
)


Hazır iki tarih dilimi arasındaki hesaplamalara örnek verirken DATESINPERIOD fonksiyonunu da kullanalım:

Syntax'ı şu şekilde:

DATESINPERIOD( 'Tarih Sütunu' ; Başlangıç Tarihi ; Periyod Sayısı ; Periyod Tipi )

Son 1 yıllık yürüyen toplam satışları aşağıdaki gibi bir formülle de bulabiliriz:

Son 1 Yıllık Yürüyen Satışlar_DATESINPERIOD := 
CALCULATE( [Satışlar] ;
      DATESINPERIOD( 'Tarih'[Tarih] ;
           LASTDATE( 'Tarih'[Tarih] ) ;
           -1 ;
           YEAR
      )
)


DATESINPERIOD son derece esnek bir fonksiyon, periyod tipi  gün, ay, çeyrek veya yıl olabilir . Periyod sayısını da  – ya da + yaparak ileriye veya geriye doğru X gün-ay-çeyrek-yıl hesaplamaları yapabiliriz.

Son 3 Aylık Yürüyen Ortalama Satış büyüklüğünü bulalım:

Son 3 Aylık Yürüyen Ortalama Satış Büyüklüğü := 
CALCULATE( AVERAGE( 'Satışlar'[Tutar] ) ;
     DATESINPERIOD( 'Tarih'[Tarih] ;
          LASTDATE( 'Tarih'[Tarih] ) ;
          -3 ;
          MONTH
      )
)


Bu örneği biraz daha geliştirelim: Son 3 Aylık şeklinde sabit değil de, kullanıcının seçebileceği bir parametreye bağlayalım. Yani Son X Aylık Yürüyen Ortalama Satış  Büyüklüğü'nü bulalım.

What If yapısını kullanarak 1-24 arasında değer alabilecek bir tablo ve parametre yaratıyorum.

Son X Aylık Yürüyen Ortalama Satış Büyüklüğü := 
VAR SonTarih = LASTDATE( 'Tarih'[Tarih] )
VAR AySayisi = SELECTEDVALUE('Ay Sayısı'[Ay Sayısı])
RETURN
CALCULATE( AVERAGE( 'Satışlar'[Tutar] ) ;
     DATESINPERIOD( 'Tarih'[Tarih] ; SonTarih ; -AySayisi ; MONTH )
)


Benzer varyasyonları arttırmak, hatta farklı kalıplarla yazmak mümkün. DAX'ta bir şeyi yapmanın birden fazla yöntemi var genelde.

Son 30 günün ortalama satış büyüklüğünü DATESINPERIOD ile değil başka bir yöntemle bulalım.

Son 30 Gün Yürüyen Ortalama Satış Büyüklüğü := 
VAR SonTarih = LASTDATE( 'Tarih'[Tarih] )
RETURN
CALCULATE( AVERAGE( 'Satışlar'[Tutar] ) ;
     FILTER( ALL( 'Tarih') ;
            'Tarih'[Tarih] >= SonTarih - 30 &&
            'Tarih'[Tarih] <= SonTarih
     )
)


Bu örneği de dilersek yukarıdaki gibi X Günlük ortalamaya çevirmek mümkün.

FIRSTDATE ile birlikte bir de stok örneği yapalım. Modelde stok hareketlerini içeren bir tablomuz var.


Herhangi bir tarihteki stoğu bulabilmek için en başından o tarihe kadar olan tüm giriş çıkış hareketlerini toplamamız lazım tablonun veri yapısına göre. Yani en başından itibaren kümülatif toplam alan bir metriğe ihtiyacımız var.

Stok := 
CALCULATE( SUMX( 'Stok' ; ('Stok'[Giriş] - 'Stok'[Çıkış] ) * 'Stok'[Birim Maliyet] ) ;
         FILTER( ALL( 'Tarih' ) ;
            'Tarih'[Tarih] <= MAX( 'Tarih'[Tarih] ) 
         )
)

Yukarıdaki bu kümülatif hesaplama kalıbını daha önce bu yazıda anlatmıştım.

Dönem başı ve dönem sonu stoklarını aşağıdaki metriklerle kolaylıkla bulabiliriz.

Dönem Başı Stok := CALCULATE( [Stok] ; FIRSTDATE( 'Tarih'[Tarih] ) )
Dönem Sonu Stok := CALCULATE( [Stok] ; LASTDATE( 'Tarih'[Tarih] ) )


** Matristeki 26-27 diye giden değerler hafta numarası.

Hazır konu stoktan açılmışken bir öneride bulunayım, sisteminizde  tarih bağımsız  ürün bazında (depo bazında vs) güncel anlık stok bilgisini tutan bir tablo varsa veya bu amaçla siz bir sorgu/prosedür yazdıysanız  bunu kullanmayın kesinlikle . İki sebepten dolayı: Muhtemelen bu sorgunun çalışması uzun sürer, daha önemlisi satışlara karşılık taşıdığımız stokların karşılaştırmasını yapamayız. Ki, stok çevrim hızı, stokta kalma süresi gibi olmazsa olmaz diyebileceğimiz çok önemli KPI'lar var.

Formülleri gayet basit :

Stok Devir Hızı := 
DIVIDE( [Satışlar] ; ( [Dönem Başı Stok] + [Dönem Sonu Stok] ) / 2 )

Bu gösterge ne kadar yüksekse işler o kadar iyidir !

Stokta Tutma Süresi bir ürünün satılana kadar ortalama kaç gün stokta kaldığını gösteren önemli bir göstergedir. Aylık, çeyrek, yıllık veya istenilen iki tarih aralığı için hesaplanabilir. Yazıyı daha da çok uzatmamak adına aylık stokta kalma süresini ayı da 30 gün kabul ederek aşağıdaki gibi bulabiliriz.

Stokta Kalma Süresi := DIVIDE( 30 ; [Stok Devir Hızı] )


Bu metrik de ne kadar düşükse -genelde- o kadar iyidir.

Bitiriyorum: FIRSTDATE/LASTDATE fonksiyonlarına benzeyen MIN/MAX, FIRSTNONBLANK/LASTNONBLANK gibi fonksiyonlar da var. Hepsi duruma göre bazen aynı şeyi gösteriyor ama aralarında önemli nüanslar var. Sonraki yazılarda LASTDATE – MAX – LASTNONBLANK üzerinden bunlara değineceğim.

Yazıdaki modeli indirebilirsiniz.

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