Ana içeriğe geç
Kesit Power BI
İleri · İleri DAX

Yapay zekânın yazdığı DAX’ı denetlemek

Copilot ve sohbet asistanlarının sık yaptığı DAX hataları (uydurma adlar, SUM yerine SUMX, toplam satırı, olgu tarihiyle zaman zekâsı, ALL, VAR zamanlaması, bölme, performans) ve bir öneriyi rapora koymadan önce uygulanacak denetim listesi.

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ç.

Yapay zekâ asistanları DAX’ı hızlı yazar; ama modelini görmeden yazar ve çalışan kodla doğru kodu ayırt etmez. Bir ölçü hata vermeden çalışıp yanlış sayı üretebilir. Bu derste asistanların en sık yaptığı hataları bizim modelde göreceğiz: her hata için önce “önerilen” kod, sonra düzeltilmiş hâli. Arka plan için “Bağlam geçişi”, “CALCULATE” ve “Zaman zekâsı” derslerine dönebilirsin.

1 · Var olmayan sütun ya da ölçü

Asistan, genel bir satış modeli varsayar ve Satislar[Ciro] ya da [Total Revenue] gibi adlar uydurur. Bu en masum hatadır, çünkü motor hemen hata verir:

Ciro (önerilen) = SUM(Satislar[Ciro])   -- böyle bir sütun yok

Asıl tehlike, adın var olup yanlış olmasıdır: Satislar[Tutar] gerçekten var ama iptalleri de içerir. Bizim modelde ciro için [Net Satış] kullanılır. Asistana soru sorarken tablo, sütun ve ölçü listesini ver; “yalnızca bu adları kullan” de.

2 · SUM × SUM ya da SUMX gereken yerde SUM

Brüt Ciro (önerilen) = SUM(Satislar[Adet]) * SUM(Satislar[BirimFiyat])

Bu kod iki toplamı çarpar: bizim modelde yaklaşık 2,97 milyar ₺ çıkar. Doğru hesap her satırda adet × fiyat yapıp sonra toplar (yaklaşık 1,29 milyon ₺, iptaller hariç):

Brüt Ciro =
CALCULATE(
    SUMX(Satislar, Satislar[Adet] * Satislar[BirimFiyat]),
    Satislar[Durum] <> "İptal"
)

Ters hata da görülür: tek bir sütunu toplamak için SUMX(Satislar, Satislar[Tutar]) yazmak. Sonuç aynıdır ama gereksizdir; SUM yeter.

3 · Gereksiz FILTER(Tablo)

Web Satışı (önerilen) = CALCULATE([Net Satış], FILTER(Satislar, Satislar[Kanal] = "Web"))
Web Satışı = CALCULATE([Net Satış], Satislar[Kanal] = "Web")

İkisi de 457.331 ₺ verir. Ama ilki tüm olgu tablosunu satır satır tarar ve genişletilmiş tabloyu filtre olarak uygular; büyük modelde yavaştır ve bazı bağlamlarda farklı sonuç verir. Kural: tek sütuna koşul koyacaksan sütun filtresi yaz, FILTER’ı ölçüye bağlı koşullar için sakla.

4 · Toplam satırında yanlış sonuç

Hedef Aşımı (önerilen) = IF([Net Satış] > [Hedef], [Net Satış] - [Hedef], 0)

Bu ölçü bir ayda hedefi aşan kategoride doğru farkı gösterir. Ama toplam satırında toplam satışla toplam hedefi karşılaştırır: bizim modelde üç yılın tamamında satış hedefin altında kaldığı için toplam 0 çıkar. Oysa tek tek aylarda ve kategorilerde aşımlar vardır. Toplamın, ayrıntıların toplamı olması gerekiyorsa ayrıntı düzeyinde dolaş:

Hedef Aşımı =
SUMX(
    CROSSJOIN(VALUES(Kategoriler[Kategori]), VALUES(Tarih[YilAy])),
    VAR Fark = [Net Satış] - [Hedef]
    RETURN IF(Fark > 0, Fark)
)

Bu hâliyle toplam 33.447 ₺ olur. Asistanlar toplam satırını neredeyse hiç düşünmez; her öneriyi bir matriste toplam satırıyla birlikte dene.

5 · Zaman zekâsında olgu tablosunun tarihi

Satış GY (önerilen) = CALCULATE([Net Satış], SAMEPERIODLASTYEAR(Satislar[Tarih]))

Yıl dilimleyicisi Tarih tablosundan gelir. Kod, olgu tablosundaki tarihleri bir yıl geri kaydırır ama Tarih[Yil] filtresi yerinde kalır: 2024 satırında “2024’te olup 2023 tarihli satışlar” istenir ve sonuç boş çıkar. Zaman zekâsı fonksiyonlarına her zaman işaretli tarih tablosunun sütununu ver: SAMEPERIODLASTYEAR(Tarih[Tarih]).

6 · ALL ile dilimleyiciyi silmek

Seçili Dönem Toplamı (önerilen) = CALCULATE([Net Satış], ALL(Tarih))

Amaç “seçili yılların toplamı” ise bu kod yanlıştır: ALL(Tarih) yıl dilimleyicisini de siler ve her satırda 1.250.772 ₺ gösterir. Seçime saygı için ALLSELECTED, yalnızca belirli bir sütunun filtresini kaldırmak için REMOVEFILTERS(Tablo[Sütun]) kullan. “FILTER, ALL, ALLEXCEPT, ALLSELECTED” dersindeki üç pay türünü hatırla.

7 · VAR, CALCULATE’ten önce hesaplanır

Web Payı (önerilen) =
VAR S = [Net Satış]
RETURN DIVIDE(CALCULATE(S, Satislar[Kanal] = "Web"), S)

Değişken tanımlandığı yerde ve bir kez hesaplanır. CALCULATE(S, …) artık bir sayıyı filtreler; sayı değişmez. Sonuç her hücrede %100 olur. Filtrelenecek ifade ölçünün kendisi olmalı:

Web Payı =
VAR Toplam = [Net Satış]
RETURN DIVIDE(CALCULATE([Net Satış], Satislar[Kanal] = "Web"), Toplam)

8 · DIVIDE yerine bölü işareti

Büyüme (önerilen) = ([Net Satış] - [Satış GY]) / [Satış GY]

İlk yıl (2022) geçen yıl boştur: payda BLANK, sonuç sonsuz olur ve kartta “∞” görünür. DIVIDE([Net Satış] - [Satış GY], [Satış GY]) bu durumda BLANK döndürür. Ayrıca payın da anlamlı olup olmadığını düşün: geçen yıl yoksa fark da anlamsızdır.

9 · Performans: iteratör içinde ölçü

Net Satış (önerilen) = SUMX(Satislar, [Net Satış])

Sonuç doğru çıkar, ama her satırda bağlam geçişi olur: 1.620 satırlık tabloda 1.620 kez, milyonluk tabloda milyonlarca kez. Ayrıca olgu tablosunda tekrar eden satırlar varsa sonuç bozulur. Ölçüyü iteratör içinde çağıracaksan küçük bir tabloda dolaş (VALUES(Urunler[Kategori]) gibi). Ayrıntı “DAX optimizasyonu” dersinde.

Denetim kontrol listesi

  1. Adlar: Her tablo, sütun ve ölçü modelde var mı? Doğru temel ölçü mü ([Net Satış] mı, Satislar[Tutar] mı)?
  2. Bilinen toplam: Sonucu bildiğin bir sayıyla karşılaştır (ör. Net Satış ≈ 1.250.772 ₺, 2024 ≈ 747.066 ₺).
  3. Toplam satırı: Matriste satırları topla; toplamla tutuyor mu, tutması gerekiyor mu?
  4. Dilimleyici: Bir yıl, bir kategori seç; sonuç beklediğin gibi değişiyor mu, değişmemesi gereken yerde sabit mi?
  5. Sınır durumları: İlk yıl, boş ay, hiç satmamış ürün, tek gün seçimi.
  6. Okunabilirlik: __PREV_YEAR gibi adları ekip standardına çevir; açıklama ekle.

DAX sorgu görünümünde test et

Ölçüyü modele eklemeden önce sorgu içinde tanımlayıp yan yana karşılaştırabilirsin. Aşağıdaki sorgu hatalı öneriyi ve doğru ölçüyü aynı tabloda gösterir; boş sütun, hatanın kanıtıdır:

DEFINE
    MEASURE Satislar[GY (önerilen)] = CALCULATE([Net Satış], SAMEPERIODLASTYEAR(Satislar[Tarih]))
EVALUATE
SUMMARIZECOLUMNS(
    Tarih[Yil],
    "Net Satış", [Net Satış],
    "GY (önerilen)", [GY (önerilen)],
    "GY (doğru)", [Satış GY]
)
Asistana daha iyi soru“Satislar[Tutar], Satislar[Durum], Tarih[Tarih] (işaretli tarih tablosu) ve [Net Satış] ölçüsü var. İptaller hariç geçen yılın aynı dönemine göre büyüme yüzdesini yaz; ilk yılda boş dönsün; yalnızca bu adları kullan.” Bağlam verdikçe hata azalır, ama denetim yine sende.
Alıştırmalara geç (7)