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
- Adlar: Her tablo, sütun ve ölçü modelde var mı? Doğru temel ölçü mü (
[Net Satış]mı,Satislar[Tutar]mı)? - Bilinen toplam: Sonucu bildiğin bir sayıyla karşılaştır (ör. Net Satış ≈ 1.250.772 ₺, 2024 ≈ 747.066 ₺).
- Toplam satırı: Matriste satırları topla; toplamla tutuyor mu, tutması gerekiyor mu?
- Dilimleyici: Bir yıl, bir kategori seç; sonuç beklediğin gibi değişiyor mu, değişmemesi gereken yerde sabit mi?
- Sınır durumları: İlk yıl, boş ay, hiç satmamış ürün, tek gün seçimi.
- Okunabilirlik:
__PREV_YEARgibi 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]
)