Doğal hiyerarşi ve ebeveyn-çocuk hiyerarşisi
Kategori → Ürün ya da Yıl → Çeyrek → Ay gibi doğal hiyerarşiler farklı sütunlarda durur ve matrise satır satır eklenir. Organizasyon şeması ise tek tabloda ebeveyn-çocuk (parent-child) biçimindedir: Calisanlar[CalisanNo] ve Calisanlar[YoneticiNo]. Derinlik sabit değildir; buna düzensiz (ragged) hiyerarşi denir.
PATH ailesi
-- Hesaplanmış sütunlar (Calisanlar tablosunda): Yol = PATH(Calisanlar[CalisanNo], Calisanlar[YoneticiNo]) -- "1|2|9" Seviye = PATHLENGTH(Calisanlar[Yol]) -- 3 Seviye1 = LOOKUPVALUE(Calisanlar[AdSoyad], Calisanlar[CalisanNo], PATHITEM(Calisanlar[Yol], 1, INTEGER)) Seviye2 = LOOKUPVALUE(Calisanlar[AdSoyad], Calisanlar[CalisanNo], PATHITEM(Calisanlar[Yol], 2, INTEGER)) Seviye3 = LOOKUPVALUE(Calisanlar[AdSoyad], Calisanlar[CalisanNo], PATHITEM(Calisanlar[Yol], 3, INTEGER))
Seviye1–3 sütunları matrisin satırlarına konunca organizasyon şeması açılıp kapanan bir hiyerarşi olur. Boş seviyeleri gizlemek için düzey bilinçli bir ölçü kullanılır:
Satış (Hiyerarşi) =
VAR Derinlik = MAX(Calisanlar[Seviye])
VAR GosterilenDuzey =
ISINSCOPE(Calisanlar[Seviye1])
+ ISINSCOPE(Calisanlar[Seviye2])
+ ISINSCOPE(Calisanlar[Seviye3])
RETURN
IF(GosterilenDuzey <= Derinlik, [Ekip Satışı])
Matris, bir çalışanın gerçek derinliğinden daha alt bir düzeyi gösteriyorsa (ör. temsilcinin altında boş bir “Seviye4”) ölçü boş döner ve o satır gizlenir. TRUE/FALSE değerleri toplanınca 1/0 olur.
Ekibin toplamı: PATHCONTAINS
Bir yöneticinin satırında, hiyerarşide altındaki herkesin toplamı:
Ekip Satışı = VAR Kisi = SELECTEDVALUE(Calisanlar[CalisanNo]) RETURN CALCULATE([Net Satış], FILTER(ALL(Calisanlar), PATHCONTAINS(Calisanlar[Yol], Kisi)))
Hiyerarşide pay: ebeveyne göre
Matriste Kategori → Ürün varken, ürün satırında ürünün kategorisi içindeki payını, kategori satırında kategorinin genel paydaki yerini göstermek:
Ebeveyne Göre Pay % =
SWITCH(
TRUE(),
ISINSCOPE(Urunler[Urun]),
DIVIDE([Net Satış], CALCULATE([Net Satış], ALLSELECTED(Urunler[Urun]))),
ISINSCOPE(Urunler[Kategori]),
DIVIDE([Net Satış], CALCULATE([Net Satış], ALLSELECTED(Urunler[Kategori]))),
1
)
ISINSCOPE en alt düzeyden başlayarak kontrol edilir: ürün düzeyinde kategori de “kapsamda”dır.
Bu modelin organizasyon ağacı
Calisanlar tablosunda 27 kişi ve üç düzey var: Genel Müdür Selim Aksoy (düzey 1), altında altı müdür (düzey 2), onların altında 20 uzman ve temsilci (düzey 3). Satış yapanlar Satış Müdürü Elif Doğan ve ekibindeki beş kişi. Satışın 183.134,35 ₺'si düzey 2'de (Elif Doğan'ın kendisi), 1.067.638,10 ₺'si düzey 3'te.
Bu yapı, gerçek şirketlerde sık görülen bir sorunu taşır: müdür hem yönetir hem satar. Matris açıldığında müdürün kendi satışı nereye düşer? Bu soru düzensiz hiyerarşinin (ragged hierarchy) özüdür.
Düzensiz hiyerarşi: boşluklar nereden gelir?
Matrise Seviye1 → Seviye2 → Seviye3 sütunları konduğunda Elif Doğan'ın satırı düzey 2'de biter; Seviye3 değeri boştur. Matris onun 183.134,35 ₺'lik kendi satışını Elif Doğan'ın altında "(Boş)" adlı bir satırda gösterir. Kullanıcı "Boş kim?" diye sorar. Üç çözüm:
| Çözüm | Artı | Eksi |
|---|---|---|
| Boş düzeyi ISINSCOPE'lu bir ölçüyle gizlemek (ana bölümdeki "Satış (Hiyerarşi)") | Model değişmez | Müdürün kendi satışı hiçbir alt satırda görünmez, yalnızca toplamında |
| Boş düzeyi kişinin kendi adıyla doldurmak | Her tutar adı olan bir satırda | Müdür kendi altında bir kez daha görünür |
| Boş düzeyi "(kendi satışı)" gibi bir etiketle doldurmak | Açık ve okunur | Etiket kuralı belgelenmeli |
-- Calisanlar tablosunda hesaplanmış sütun
Seviye3 (Dolu) =
VAR Kendi = Calisanlar[AdSoyad]
VAR Uc = LOOKUPVALUE(
Calisanlar[AdSoyad], Calisanlar[CalisanNo],
PATHITEM(Calisanlar[Yol], 3, INTEGER)
)
RETURN IF(PATHLENGTH(Calisanlar[Yol]) < 3, Kendi & " (kendi satışı)", Uc)
Hangi çözümü seçersen seç, matrisin toplamları değişmez; değişen, kullanıcının tutarı nerede bulduğudur. Organizasyon raporlarında en az soru getiren seçenek genellikle üçüncüsüdür.
PATH ailesi: derinlemesine
| Fonksiyon | Gamze Özkan için (Yol = "1|2|8") | Not |
|---|---|---|
PATHLENGTH(Yol) | 3 | Düzey |
PATHITEM(Yol, 1, INTEGER) | 1 | Kök (Genel Müdür) |
PATHITEMREVERSE(Yol, 2, INTEGER) | 2 | Sondan ikinci: doğrudan yönetici |
PATHCONTAINS(Yol, 2) | DOĞRU | Elif Doğan'ın ağacında mı? |
PATHITEM'in üçüncü bağımsız değişkenini unutma: varsayılan dönüş türü metindir. Metin "2" ile tamsayı CalisanNo, LOOKUPVALUE'da eşleşmez. Microsoft Learn'deki kurallar, PATH sütunu yenilemede hata vermeden önce veri kalitesini kontrol etmeni gerektirir:
- Kimlik ve ebeveyn sütunu aynı türde olmalı: ikisi de metin ya da ikisi de tamsayı.
- Ebeveyn sütunu boşsa PATH yalnızca kişinin kendi kimliğini döndürür (kök).
- Ebeveyn sütunundaki her değer kimlik sütununda bulunmalı.
- Kimlikte dikey çizgi (|) varsa hata alırsın.
- Aynı kimlik farklı ebeveynlerle iki kez geçiyorsa hata alırsın.
- DirectQuery modunda hesaplanmış sütunda ve RLS kuralında desteklenmez.
Yenilemeden önce şu sorguyla "yöneticisi tabloda olmayan" kayıtları ara:
EVALUATE EXCEPT(VALUES(Calisanlar[YoneticiNo]), VALUES(Calisanlar[CalisanNo]))
Bu modelde tek satır gelir ve değeri boştur: kök çalışanın boş YoneticiNo'su. Başka bir değer gelirse PATH o çalışanda hata verecek demektir.
Yönetici bazında toplama: üç farklı soru
İK direktörü "Elif Doğan'ın satışı ne kadar?" diye soruyor. Bu cümle üç farklı sayıya karşılık gelebilir:
| Soru | Ölçü fikri | Elif Doğan | Selim Aksoy |
|---|---|---|---|
| Kişinin kendi satışı | [Net Satış] | 183.134,35 | boş |
| Doğrudan bağlıları | Calisanlar[YoneticiNo] = Kisi | 1.067.638,10 | 183.134,35 |
| Tüm alt ağaç (kendisi dahil) | PATHCONTAINS(Calisanlar[Yol], Kisi) | 1.250.772,45 | 1.250.772,45 |
Mekanizma: FILTER(ALL(Calisanlar), PATHCONTAINS(Calisanlar[Yol], Kisi)), satırdaki kişiye ait filtreyi kaldırır ve yerine ekibin satırlarını koyar. Bu filtre TemsilciNo ilişkisi üzerinden Satislar'a iner. Raporda hangi sayının gösterildiği başlıkta yazmalı; yoksa üç ayrı toplantıda üç ayrı rakam konuşulur.
Ekip içindeki pay da aynı mantıkla hesaplanır: payda, kişinin yöneticisinin alt ağacıdır. Gamze Özkan'ın payı Elif Doğan ağacının %21,2'si; Elif Doğan'ın kendi payı ise Genel Müdür ağacının %14,6'sı.
PATHCONTAINS(Calisanlar[Yol], ...USERPRINCIPALNAME()...)), ölçüdeki ALL(Calisanlar) RLS'nin gizlediği satırları geri getirmez. Müdür kendi ekibinin toplamını doğru görür; temsilci yalnızca kendini görür. "Şirket toplamına göre pay" ise RLS altında "görebildiğim toplama göre pay" olur. Bu farkı raporun kullanım notuna yaz.ISINSCOPE ile düzeye göre farklı hesap
Satış direktörü Departman → Çalışan matrisi istiyor: çalışan satırında kişinin tüm alt ağacının satışı, departman satırında departmanın satışı görünsün.
Düzeye Göre Ekip Satışı =
SWITCH(
TRUE(),
ISINSCOPE(Calisanlar[AdSoyad]), [Ekip Satışı],
ISINSCOPE(Departmanlar[Departman]), [Net Satış],
[Net Satış]
)
Bunun bir bedeli var: alt toplam artık çocukların toplamı değildir. Satış departmanı satırı 1.250.772,45 ₺ gösterir; altındaki çalışan satırlarının toplamı ise 2.318.410,55 ₺'dir, çünkü Elif Doğan'ın satırı ekibinin satışını da içerir. Kullanıcı satırları toplarsa yanlış sonuca varır. Bu tür ölçülerde:
- Ölçünün adı farkı söylesin ("Ekip Satışı (alt ağaç)").
- Kenara bir not ekle: "Çalışan satırları toplanmaz."
- ISINSCOPE kullan, HASONEVALUE değil: dilimleyicide tek departman seçiliyken HASONEVALUE toplam satırında da DOĞRU döner; ISINSCOPE yalnızca o düzey matriste gerçekten açıkken DOĞRU döner.
Kontrol listesi
- Kök kayıt dışında, yöneticisi tabloda olmayan çalışan var mı? (EXCEPT sorgusu)
- PATHITEM'de dönüş türü INTEGER mı?
- Müdürün kendi satışı matriste adı olan bir satırda görünüyor mu?
- "Kendi", "doğrudan bağlı" ve "alt ağaç" sayılarından hangisi gösteriliyor?
- RLS altında ALL'ın göremeyeceği satırlar düşünüldü mü?
- Düzeye göre değişen ölçüde alt toplamların çocukların toplamı olmadığı belirtildi mi?