Ana içeriğe geç
Kesit Power BI
Temel · DAX Temelleri

DAX'ta tarih, metin ve sayma fonksiyonları

Altı sayma fonksiyonunun farkı, teslim süresini DATEDIFF ile hesaplamak, EOMONTH, WEEKDAY, NETWORKDAYS, FORMAT ile ay adı üretmek ve metin fonksiyonları. Hangisi hesaplanmış sütunda, hangisi ölçüde kullanılır?

Uygulamada aç, 7 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

Toplama fonksiyonları dersinde SUM, COUNTROWS ve DISTINCTCOUNT ile tanıştın. Bu derste üç küçük ama her gün kullanılan aileyi tamamlıyoruz: sayma, tarih ve metin fonksiyonları. Örneklerin hepsi Anadolu Market modelinden; sayılar bu modelden hesaplandı.

Sayma ailesi: altı fonksiyon, altı farklı soru

“Kaç tane?” sorusunun DAX'ta birden çok cevabı var. Fark, boş (BLANK) hücreleri ve tekrar eden değerleri nasıl ele aldıklarındadır. Satislar[KargoGun] sütununda bazı satırlar boştur; bu sütun farkları görmek için idealdir.

FonksiyonNe sayar?Satislar[KargoGun] için sonuç
COUNTROWS(Satislar)Tablonun satırlarını; sütunla ilgilenmez1.620
COUNTBoş olmayan hücreleri (sayı, tarih, metin)1.489
COUNTABoş olmayan hücreleri; TRUE/FALSE dahil her türü1.489
COUNTBLANKBoş hücreleri131
DISTINCTCOUNTFarklı değerleri; BLANK da bir değer sayılır15
DISTINCTCOUNTNOBLANKFarklı değerleri; BLANK hariç14

Kargo günü 0 ile 13 arasında 14 farklı değer alıyor. DISTINCTCOUNT boş hücreyi de ayrı bir değer saydığı için 15 döndürür. Aynı tuzak müşteri tablosunda da var: 150 müşterinin 7'sinin şehri boş. DISTINCTCOUNT(Musteriler[Sehir]) 13, DISTINCTCOUNTNOBLANK(Musteriler[Sehir]) 12 verir. “Kaç şehre satış yapıyoruz?” sorusunun doğru cevabı 12'dir.

Boş Kargo Günü = COUNTBLANK(Satislar[KargoGun])
Şehirli Müşteri = COUNTA(Musteriler[Sehir])
COUNT ile COUNTAGüncel DAX'ta COUNT sayı, tarih ve metin değerlerini sayar; yalnızca TRUE/FALSE sütunlarında çalışmaz. Mantıksal (Boolean) bir sütunu saymak için COUNTA kullan. Pratikte ikisi çoğu sütunda aynı sonucu verir.

Boş değerin nedenini de sor: 131 boş kargo gününün 121'i iptal edilen siparişlerde (teslimat hiç olmayacak), 10'u ise hâlâ kargoda olan siparişlerde (henüz bilinmiyor). Sayı aynı, anlamı farklı. Bu konuya Keşifçi veri analizi dersinde döneceğiz.

Tarih fonksiyonları

FonksiyonÖrnekSonuç
YEAR, MONTH, DAYMONTH(DATE(2024, 3, 5))3
DATE(yıl, ay, gün)DATE(2024, 3, 5)5 Mart 2024
EOMONTH(tarih, ay kaydırma)EOMONTH(DATE(2024, 2, 10), 0)29 Şubat 2024 (ayın son günü)
WEEKDAY(tarih, 2)WEEKDAY(DATE(2024, 3, 4), 2)1 (Pazartesi = 1, Pazar = 7)
DATEDIFF(başlangıç, bitiş, aralık)DATEDIFF(DATE(2024, 1, 31), DATE(2024, 2, 1), MONTH)1
NETWORKDAYS(başlangıç, bitiş)NETWORKDAYS(DATE(2024, 3, 1), DATE(2024, 3, 31))21

WEEKDAY'in ikinci bağımsız değişkeni haftanın nereden başlayacağını söyler. Varsayılan (1) Pazar = 1'dir; Türkiye'de alışılan sıra için 2 kullan. Modeldeki Tarih[GunNo] sütunu tam olarak WEEKDAY(Tarih[Tarih], 2) ile aynıdır.

DATEDIFF tam ayları değil, geçilen sınırları sayar: 31 Ocak'tan 1 Şubat'a bir gün vardır, ama bir ay sınırı geçildiği için sonuç 1'dir. Aralık olarak DAY, WEEK, MONTH, QUARTER, YEAR (ve saat için HOUR, MINUTE, SECOND) yazılabilir. İkinci tarih birinciden küçükse sonuç negatiftir.

Ortalama Teslim Süresi =
AVERAGEX(
    FILTER(Satislar, NOT ISBLANK(Satislar[TeslimTarihi])),
    DATEDIFF(Satislar[Tarih], Satislar[TeslimTarihi], DAY)
)

Sonuç 3,12 gündür; modeldeki hazır [Ortalama Kargo Günü] ölçüsüyle aynı. Peki FILTER'ı atlarsan ne olur?

Teslim Süresi (hatalı) =
AVERAGEX(Satislar, DATEDIFF(Satislar[Tarih], Satislar[TeslimTarihi], DAY))
Boş tarih sıfır değildirTarih hesaplarında boş bir tarih, DAX'ın tarih başlangıcı olan 30 Aralık 1899 gibi işlenebilir. NETWORKDAYS'in belgesi bunu açıkça söyler: tarihlerden yalnızca biri boşsa 30.12.1899 kabul edilir. Bu uygulamanın motorunda yukarıdaki hatalı ölçü −1.596,7 gün döndürür. Teslim tarihi boş satırları her zaman önce ayıkla.

NETWORKDAYS(başlangıç, bitiş, [hafta sonu], [tatiller]) iş günlerini sayar. Varsayılan hafta sonu Cumartesi–Pazar'dır (kod 1); tatilleri { DATE(2024, 4, 10), DATE(2024, 4, 11) } gibi tek sütunlu bir tabloyla verirsin. Başlangıç ve bitiş dahildir: aynı gün teslim edilen bir sipariş 1 iş günü sayılır. Teslimatlarda ortalama NETWORKDAYS 2,97 çıkar; “kaç iş günü sürdü?” sorusu için 1 çıkarırsın.

TODAY ve FORMAT: iki tuzak

TODAY() bilgisayarın bugünkü tarihini döndürür. Ölçüde her sorguda, hesaplanmış sütunda yalnızca yenilemede hesaplanır. Bu modelin verisi 31 Aralık 2024'te biter; “son 30 gün” ölçüsünü TODAY() ile yazarsan bugün boş sonuç alırsın. Geçmiş verili raporlarda “bugün” olarak verinin son tarihini kullan: CALCULATE(MAX(Satislar[Tarih]), REMOVEFILTERS()). Uygulamanın motoru tutarlı sonuç versin diye TODAY()'i 31.12.2024 kabul eder.

FORMAT(değer, biçim) bir değeri metne çevirir. Model kültürü Türkçe olduğunda ay adları Türkçe gelir:

İfadeSonuç
FORMAT(DATE(2024, 3, 5), "MMMM yyyy")Mart 2024
FORMAT(DATE(2024, 3, 5), "yyyy-MM")2024-03
FORMAT(DATE(2024, 3, 5), "dddd")Salı
FORMAT(1234.5, "#,0.00")1.234,50
Seçili Ay Metni =
IF(
    HASONEVALUE(Tarih[YilAy]),
    "Satışlar · " & FORMAT(MAX(Tarih[Tarih]), "MMMM yyyy"),
    "Satışlar · tüm dönem"
)
FORMAT sayıyı metne çevirirÜç sonucu var. (1) Metin döndüren bir ölçü sütun ya da çizgi grafiğin Y eksenine konamaz; Microsoft'un belgesi de bunu açıkça söyler. (2) Metin olarak sıralanır: "Ağustos", "Aralık"tan önce gelir; "10" ise "9"dan önce. (3) FORMAT(BLANK()) boş metin ("") döndürür, BLANK değil. Ölçü artık hiç boş olmadığı için tablo görseli satışı olmayan tüm satırları da gösterir. Sayıyı yalnızca görünüşü için biçimlendiriyorsan FORMAT yerine ölçünün biçim ayarını ya da dinamik biçim dizesini kullan.

Metin fonksiyonları

FonksiyonÖrnekSonuç
LEFT / RIGHT / MIDLEFT("Ankara", 3), MID("ABCDEF", 2, 3)Ank, BCD
LENLEN("Antalya")7
UPPER / LOWERUPPER(Musteriler[Sehir])BURSA
SEARCH / FINDSEARCH("set", Urunler[Urun], 1, 0)Bulunduğu konum; yoksa 0
SUBSTITUTESUBSTITUTE("a-b-c", "-", "")abc
TRIMTRIM(" Kot Pantolon ")Kot Pantolon (baştaki, sondaki ve aradaki fazla boşluklar gider)
CONCATENATE / &CONCATENATE("a", "b"), "a" & "b" & "c"CONCATENATE yalnızca iki değer alır; & sınırsızdır
COMBINEVALUESCOMBINEVALUES("|", Satislar[SiparisNo], Satislar[UrunNo])1|27 (birleşik anahtar)

SEARCH büyük-küçük harfe duyarsızdır ve joker karakter kabul eder; FIND duyarlıdır. İkisi de bulamazsa hata verir; dördüncü bağımsız değişkenle (ör. 0) bunun yerine bir değer döndürmelerini söylersin. Ürün adında “set” geçen üç ürünü bulmak:

EVALUATE
FILTER(VALUES(Urunler[Urun]), SEARCH("set", Urunler[Urun], 1, 0) > 0)

Sonuç: Çaydanlık Seti, Seramik Kupa Seti, Dambıl Seti 10kg. COMBINEVALUES ise iki sütunu ayraçla birleştirip tek bir anahtar üretir. Tek sütunlu ilişki kurulması gereken yerlerde (ör. sipariş + ürün) kullanılır; DirectQuery'de bu birleşik anahtarla kurulan ilişkiler için iyileştirilmiştir.

EVALUATE
TOPN(5,
    ADDCOLUMNS(VALUES(Musteriler[Sehir]),
        "Büyük harf", UPPER(Musteriler[Sehir]),
        "İlk 3", LEFT(Musteriler[Sehir], 3),
        "Uzunluk", LEN(Musteriler[Sehir])),
    Musteriler[Sehir], ASC)

Hesaplanmış sütunda mı, ölçüde mi?

Bu fonksiyonların çoğu tek bir değer üzerinde çalışır. Nerede kullanacağın, sonucun bir satıra mı yoksa bir seçime mi ait olduğuna bağlıdır:

İhtiyaçYerNeden?
Sipariş satırının teslim süresi, ürün kısa adı, sipariş ayı etiketiHesaplanmış sütun (daha iyisi: Power Query)Her satıra ait sabit bir etiket; dilimleyicide ve eksende kullanılır
Ortalama teslim süresi, boş kargo günü sayısıÖlçüFiltreye göre değişen bir toplam
“Mart 2024” başlığıÖlçüKullanıcının seçimine bağlı; satırda saklanamaz
Ay adı, yıl-ay, haftanın günüTarih tablosunun sütunuModelde zaten var: Tarih[Ay], Tarih[YilAy], Tarih[HaftaninGunu]
Ölçüde satır fonksiyonuÖlçüde DATEDIFF(Satislar[Tarih], …) gibi bir sütunu doğrudan yazamazsın; ölçünün “şu anki satırı” yoktur. Satır satır hesap için AVERAGEX, SUMX, FILTER gibi bir yineleyici kullan. Ayrıntısı Yineleyiciler: SUMX, AVERAGEX ve RELATED dersinde.
Alıştırmalara geç (7)