DAX sorgu görünümü
Power BI Desktop'taki DAX sorgu görünümü (ve DAX Studio gibi araçlar), bir tablo döndüren sorgular çalıştırır. Ölçüleri görsel kurmadan test etmenin, veriyi incelemenin ve hata ayıklamanın en hızlı yoludur. Bu uygulamadaki DAX Playground'nun “Sorgu” modu da aynıdır.
EVALUATE
SUMMARIZECOLUMNS(
Kategoriler[Kategori],
Tarih[Yil],
"Net Satış", [Net Satış],
"Hedef", [Hedef]
)
ORDER BY Kategoriler[Kategori], Tarih[Yil]
Tablo fonksiyonları
| Fonksiyon | Ne döndürür? |
|---|---|
SUMMARIZECOLUMNS(sütunlar…, "Ad", ifade…) | Grup başına satır + hesaplanmış sütunlar. Görsellerin arka planda ürettiği sorgu budur. Tüm ölçüleri boş olan satırları atar. |
SUMMARIZE(tablo, sütunlar…) | Tablodaki var olan grup kombinasyonları. Hesap eklemek için ADDCOLUMNS ile birlikte kullanılması önerilir. |
ADDCOLUMNS(tablo, "Ad", ifade…) | Tabloya hesaplanmış sütun ekler (her satırda bağlam geçişiyle). |
SELECTCOLUMNS(tablo, "Ad", ifade…) | Yalnızca seçilen ya da yeniden adlandırılan sütunlar. |
TOPN(n, tablo, ifade) | İlk n satır. |
FILTER, VALUES, ALL, CALCULATETABLE | Süzülmüş ya da filtresiz tablolar. |
{ }, ROW, GENERATESERIES | Elle tablo oluşturma. |
Sorgu içinde ölçü tanımlamak
DEFINE
MEASURE Satislar[Marj] = DIVIDE([Brüt Kâr], [Net Satış])
EVALUATE
TOPN(5, SUMMARIZECOLUMNS(Urunler[Urun], "Satış", [Net Satış], "Marj", [Marj]), [Satış])
ORDER BY [Satış] DESC
DEFINE MEASURE modeli değiştirmeden geçici bir ölçü tanımlar. Desktop'ta bu ölçüyü tek tıkla modele ekleyebilirsin.
Tek değer görmek
EVALUATE { [Net Satış] }
Birden çok değeri tek satırda görmek için ROW kullanılır:
EVALUATE ROW("Satış", [Net Satış], "Marj", [Kâr Marjı %])
DAX sorgu görünümü bir test tezgâhıdır
Finans, "Net Satış" tanımından iadelerin de düşülmesini istiyor. Modeldeki ölçüyü hemen değiştirirsen ona bağlı onlarca ölçü ve rapor aynı anda değişir. Önce sorgu içinde dene:
DEFINE
MEASURE Satislar[Net Satış (İadesiz)] =
CALCULATE([Toplam Satış], NOT Satislar[Durum] IN {"İptal", "İade"})
EVALUATE
SUMMARIZECOLUMNS(
Tarih[Yil],
"Eski", [Net Satış],
"Yeni", [Net Satış (İadesiz)],
"Fark", [Net Satış] - [Net Satış (İadesiz)]
)
ORDER BY Tarih[Yil]
Fark 2022'de 11.621,15 ₺, 2023'te 26.035,75 ₺, 2024'te 43.178,45 ₺: bu, iade tutarlarıdır. Finansa "bu değişiklik 2024 net satışını 43 bin ₺ düşürür" diyebilirsin. Power BI Desktop'taki iş akışı (Microsoft Learn'e göre):
- Veri bölmesinde ölçüye sağ tık → Hızlı sorgular (Quick queries) → Değerlendir (Evaluate), Tanımla ve değerlendir (Define and evaluate) ya da Başvurularla tanımla ve değerlendir (Define with references and evaluate). Sonuncusu, ölçünün dayandığı ölçüleri de DEFINE bloğuna getirir.
- Tanımı düzenle, çalıştır, sonuçları eski tanımla karşılaştır.
- Ölçünün üstündeki CodeLens bağlantısı Modeli güncelle: Ölçünün üzerine yaz (Update model: Overwrite measure) ya da şeritteki Modeli değişikliklerle güncelle (Update model with changes) ile modele yaz.
- Sorgudaki MEASURE, modelde aynı adlı bir ölçü varsa onu yalnızca o sorgu boyunca geçersiz kılar; model değişmez.
- Ölçünün üstüne
///ile yazdığın açıklama, modele eklenince ölçünün açıklaması olur. Belgeleme işini burada yapmış olursun. - Sorgu sekmeleri Desktop dosyasıyla kaydedilir. Power BI proje (PBIP) biçiminde her sekme, anlamsal model klasöründeki DAXQueries klasörüne .dax dosyası olarak yazılır; yani test sorguların Git'e girer.
- Canlı bağlantıda (live connect) model ölçüleri görüntülenemez ve "Modeli güncelle" seçenekleri yoktur.
Ölçü doğrulama sorguları
Her yeni ya da değiştirilmiş ölçü için birkaç sabit test yaz. Testin cevabı tek bir satır olsun; sonuç "GEÇTİ / KALDI" diye okunsun:
EVALUATE
VAR Beklenen = 1250772.45
RETURN
ROW(
"Net Satış", [Net Satış],
"Durum", IF(ABS([Net Satış] - Beklenen) < 0.01, "GEÇTİ", "KALDI")
)
| Test | Sorgu fikri | Bu modelde |
|---|---|---|
| Toplam tutarlılığı | [Net Satış] ile SUMX(VALUES(Kategoriler[Kategori]), [Net Satış]) eşit mi? | İkisi de 1.250.772,45 |
| Paylar toplamı | SUMX(VALUES(Kategoriler[Kategori]), [Kategori Payı %]) = 1 mi? | 1 |
| Zaman zekâsı | 31 Aralık 2024'teki [Satış YTD] = 2024 yılının satışı mı? | İkisi de 747.065,70 |
| Hedef | Kategorilere dağıtılmış hedef toplamı = genel hedef mi? | 1.299.300 |
| Kaynakla mutabakat | Kaynak sistemdeki (SQL, ERP) toplamla aynı mı? | Kaynak sorgusuyla karşılaştır |
Kayan nokta tuzağı: [Net Satış] - SUMX(...) sıfır değil, −0,000000000466 çıkar. Testleri doğrudan eşitlikle değil, küçük bir toleransla (ABS(fark) < 0.01) ya da ROUND ile yaz; yoksa doğru ölçü "KALDI" der.
SUMMARIZECOLUMNS + TREATAS: görseli sorguda kurmak
Bir görselin rakamı sorgulanıyor: "2024'te Web ve Mobil'de kategori satışları". Performans Analizi'nden görselin sorgusunu kopyaladığında hep aynı şekli görürsün: gruplama sütunları, dilimleyicileri temsil eden filtre tabloları ve ölçüler.
DEFINE
MEASURE Satislar[Dijital Marj] = DIVIDE([Brüt Kâr], [Net Satış])
EVALUATE
SUMMARIZECOLUMNS(
Kategoriler[Kategori],
TREATAS({2024}, Tarih[Yil]),
TREATAS({"Web", "Mobil"}, Satislar[Kanal]),
"Satış", [Net Satış],
"Marj", [Dijital Marj]
)
ORDER BY [Satış] DESC
Elektronik 168.910,60 ₺ ile başta, Hediye 8.700 ₺ ile sonda. Filtre tabloları dilimleyici gibi davranır; değerleri, gruplama satırları oluşturulmadan önce uygulanır. Üç kural:
- SUMMARIZECOLUMNS sıra garantisi vermez; testlerde her zaman ORDER BY yaz.
- Modeldeki "Sütuna göre sırala" (Sort by column) ayarı sorgu sonucuna uygulanmaz. Ay adlarını doğru sıralamak için AyNo'yu da sorguya alıp ona göre sırala.
- Sonuç ızgarasındaki sıralama ve filtre yalnızca dönen satırlara uygulanır. Sorgu başına sınır 1.000.000 değerdir (20 sütunda en fazla 50.000 satır); büyük sonuçları doğrularken filtreyi sorgunun içine yaz.
ORDER BY, START AT ve DEFINE VAR
START AT, ORDER BY'ın içinde yer alır ve sonucun hangi değerden başlayacağını belirler. Değerler sabit olmalı; ORDER BY sütun sayısından fazla değer verilemez. Büyük bir listeyi sayfa sayfa dışa aktarırken işe yarar. Bu uygulamanın motoru START AT'i desteklemez:
EVALUATE SUMMARIZECOLUMNS(Urunler[Urun], "Satış", [Net Satış]) ORDER BY Urunler[Urun] ASC START AT "M"
İkinci bir tuzak: ORDER BY, TOPN'in hangi satırları seçeceğini belirlemez; yalnızca seçilenleri sıralar. "İlk 10" sorusunun sırası TOPN'in kendi sıralama bağımsız değişkenindedir.
DEFINE bloğunda VAR ile sorgu genelinde geçerli bir eşik tanımlayabilirsin. Belgeler DEFINE TABLE ve DEFINE COLUMN için "iç kullanım içindir, önerilmez" diyor; sorgu içi tablolar için VAR kullan:
DEFINE
VAR Esik = 0.3
EVALUATE
FILTER(SUMMARIZECOLUMNS(Urunler[Urun], "Marj", [Kâr Marjı %]), [Marj] < Esik)
Marjı %30'un altında kalan 9 ürün gelir. Eşiği değiştirip yeniden çalıştırmak tek bir sayıyı düzenlemek kadar kolaydır.
Sorgu ile veri kalitesi kontrolü
Yeni bir veri kaynağı bağlandığında, rapor yazmadan önce tek bir "sağlık" sorgusu çalıştır. Bu modelde sonuçlar şöyle:
| Kontrol | İfade fikri | Sonuç | Yorum |
|---|---|---|---|
| Anahtar benzersiz mi? | COUNTROWS(Satislar) - DISTINCTCOUNT(Satislar[SatirNo]) | 0 | Bağlam geçişi güvenli |
| Yetim ürün satırı | FILTER(Satislar, ISBLANK(RELATED(Urunler[Urun]))) | 0 | Her satışın ürünü var |
| Negatif tutar | Satislar[Tutar] < 0 | 0 | İadeler Durum ile işaretli |
| Teslim, siparişten önce | TeslimTarihi < Tarih | 0 | Tarih mantığı tutarlı |
| Boş kargo günü | ISBLANK(Satislar[KargoGun]) | 131 | 121 iptal + 10 kargoda; beklenen |
| Tarih tablosu kesintisiz mi? | COUNTROWS(Tarih) ile gün farkı + 1 | 1.096 = 1.096 | Eksik gün yok |
| Hiç almamış müşteri | ISEMPTY(RELATEDTABLE(Satislar)) | 14 | Ortalama ölçülerinde dikkat |
| Şehri boş müşteri | COUNTBLANK(Musteriler[Sehir]) | 7 | Harita ve bölge raporunda "(Boş)" |
| Hiç satılmamış ürün | ISEMPTY(CALCULATETABLE(Satislar)) | 2 | Koşu Bandı, Gurme Lokum Kutusu |
EVALUATE
ROW(
"Satır", COUNTROWS(Satislar),
"Yetim ürün", COUNTROWS(FILTER(Satislar, ISBLANK(RELATED(Urunler[Urun])))) + 0,
"Boş kargo günü", COUNTROWS(FILTER(Satislar, ISBLANK(Satislar[KargoGun]))) + 0,
"Tarih satırı", COUNTROWS(Tarih),
"Gün sayısı", DATEDIFF(MIN(Tarih[Tarih]), MAX(Tarih[Tarih]), DAY) + 1,
"Almayan müşteri", COUNTROWS(FILTER(Musteriler, ISEMPTY(RELATEDTABLE(Satislar)))) + 0
)
Boş bir FILTER üzerinde COUNTROWS 0 değil BLANK döndürür. Rapor ya da test çıktısında "0" görmek istiyorsan + 0 ekle.