درک تصویری فیلتر کانتکست (Filter Context) در DAX
فیلتر کانتکست یکی از مفاهیم پایهای و اساسی در DAX است که برای نوشتن کدهای مؤثر و دقیق باید به خوبی آن را درک کرد. در این مقاله، ما فیلتر کانتکست را به صورت بصری توضیح میدهیم — یعنی از یک نمایش گرافیکی استفاده میکنیم که تعاملات مختلف موجود در فیلتر کانتکست را هنگام استفاده از المانهای تصویری (Visuals)، فیلترها (Filters) و اسلایسرها (Slicers) در یک گزارش، به تصویر میکشد.
این اولین قدم برای برنامهریزی تغییراتی است که برای رسیدن به نتیجهی دلخواه نیاز است. این تغییرات معمولاً از طریق تابع CALCULATE
اعمال میشوند؛ تابعی که میتواند فیلترهای موجود در فیلتر کانتکست را حذف، اضافه یا جایگزین کند.
این مقاله دیدگاه متفاوتی نسبت به موضوعی ارائه میدهد که در مقالات دیگر نیز دربارهاش صحبت شده است؛ برای درک عمیقتر این مفهوم مهم در DAX، پیشنهاد میکنیم مقالات دیگر را نیز مطالعه کنید.
هر سلول، فیلتر کانتکست متفاوتی دارد
هر عددی که در یک گزارش میبینید، حاصل ارزیابی یک عبارت DAX در یک فیلتر کانتکست مشخص است. یک عبارت ممکن است نتایج متفاوتی تولید کند، چون هر بار در یک فیلتر کانتکست متفاوت اجرا میشود. به همین دلیل، هر سلول در یک ماتریس (Matrix) و هر نقطه داده در یک نمودار، فیلتر کانتکست خاص خود را دارد.
ما فیلتر کانتکست را با توصیف فیلترهایی که بر روی یک سلول خاص در یک ماتریس تصویری اعمال شدهاند، بررسی میکنیم. تصویر زیر فیلتر کانتکست مربوط به سلول مشخصشدهای را نشان میدهد که مقدار ۸٬۷۷۶٫۵۴ را باز میگرداند.

سلول موردنظر، مقدار Sales Amount (میزان فروش) در سال ۲۰۱۹ را برای محصولات آبی برند Contoso که در ایالات متحده و کانادا فروخته شدهاند، نشان میدهد. هر فیلتر در فیلتر کانتکست در واقع یک جدول است که شامل لیستی از مقادیر «قابل مشاهده» برای یک یا چند ستون از مدل معنایی (semantic model) میباشد.
در این مثال ابتدایی، چهار فیلتر وجود دارد که هرکدام فقط یک ستون را فیلتر کردهاند:
ستون Brand فقط مقدار Contoso را دارد،
ستون Color فقط مقدار Blue را دارد،
ستون Year فقط مقدار ۲۰۱۹ را دارد،
و ستون Country شامل دو مقدار (Canada و United States) است که کاربر در اسلایسر انتخاب کرده.
تمام توابعی که در یک فیلتر کانتکست ارزیابی میشوند، فقط سطرهایی را بازمیگردانند که از طریق این فیلترها «قابل مشاهده» هستند. فیلتر کانتکست، جداول موجود در مدل را به شیوهای بسیار کارآمد فیلتر میکند.
نکته مهمتر اینکه، این فیلترها فقط زمانی “مصرف” میشوند که یک عمل تجمیعی (Aggregation) یا تکرارشونده (Iterator) اجرا شود. در ادامه خواهیم دید که با استفاده از تابع CALCULATE
میتوان قبل از اجرای یک تجمیع هزینهبر، فیلتر کانتکست را دستکاری کرد، و این کار هم انعطافپذیری را افزایش میدهد و هم کارایی را بهتر میکند.
فیلتر، یک جدول است
اولین مفهوم مهم این است که فیلتر در فیلتر کانتکست، در واقع یک جدول است که شامل لیستی از مقادیر برای یک یا چند ستون میباشد.
در مثال قبل، اسلایسر شامل دو کشور انتخابشده بود، و این دو مقدار در جدول مربوط به فیلتر Country قرار میگیرند. اما حتی اگر فیلتر از طریق یک عملگر مانند «کمتر از» (less than
) برای یک ستون عددی تعریف شده باشد، باز هم فیلتر بهصورت لیستی از مقادیر موجود در آن ستون نمایش داده میشود؛ البته فقط مقادیری که شرط را برقرار میکنند.
برای مثال، اگر در پنل فیلتر گفته شده باشد که Net Price < 10.00، فیلتر مربوطه شامل لیستی از مقادیر یکتای ستون Net Price است که این شرط را برآورده میکنند. تعداد مقادیر موجود در این فیلتر، بستگی دارد به تعداد مقادیر یکتای موجود در آن ستون که شرایط فیلتر را داشته باشند.

ما میدانیم که راه شهودیتری برای نمایش فیلتر کانتکست این است که شرط فیلتر را بهجای لیست مقادیر یکتا بنویسیم. در تصویر قبلی، ممکن است وسوسه شویم که بهجای لیست مقادیر یکتای ستون Net Price که شرط «کمتر از ۱۰» را دارند، فقط بنویسیم «< 10.00». این کار تا حدی جواب میدهد، اما نه همیشه.
در واقع، وقتی فیلترها پیچیدهتر میشوند، دیگر نمیتوان فقط با نوشتن شرط، نتیجه را دقیقاً توصیف کرد. اگر میخواهی این موضوع رو بیشتر بررسی کنی، میتونی در فایل نمونه از طریق DAX Query View در Power BI Desktop، کوئریای به نام “Complex filters” رو نگاه کنی. البته این بررسی در حیطهی اهداف این مقاله نیست.
رسیدن به فیلتر کانتکست هدف (Target Filter Context)
وقتی یک محاسبه مینویسی، معمولاً میتونی همهی عددهایی که در این محاسبه نقش دارن رو – چه در یک ویژوال یا در ویژوالهای جداگانه – نمایش بدی. هر عدد در گزارش، حاصل اجرای یک معیار (Measure) در یک فیلتر کانتکست مشخصه.
پس هر زمان به اون عدد نیاز داشته باشیم، کافیه که معیار رو در همون فیلتر کانتکست ارزیابی کنیم. بنابراین، پیش از نوشتن فرمول DAX، کار خوبی هست که فیلتر کانتکست هر بخش از محاسبه رو به زبان ساده توصیف کنیم.
مثلاً، فرض کن میخوایم یک معیار با نام % of Color بنویسیم که درصد فروش (Sales Amount) رو برای هر رنگ نشون بده.
گزارش زیر، درصد هر رنگ رو در برند Contoso فقط برای دو کشور (Canada و United States) نشون میده.
قبل از نوشتن هر کدی در DAX، میتونیم محاسبه رو اینطور به زبان ساده توضیح بدیم:
تقسیم مقدار فروش مربوط به یک رنگ (مثلاً: 11,791.62 برای محصولات آبی در برند Contoso) بر مجموع فروش همهی رنگها (مثلاً: 202,753.05 برای تمام رنگهای محصول در برند Contoso).
در تصویر بعدی، صورت (numerator) و مخرج (denominator) این تقسیم را برجسته کردهایم و فیلتر کانتکست مربوط به هرکدام را توضیح دادهایم.

ما میتوانیم مژر % of Color را بهصورت تقسیم بین دو مژر بنویسیم: Sales Amount و Sales All Colors:

معیار موجود Sales Amount در فیلتر کانتکست فعلی، مقدار مورد نیاز برای صورت (numerator) در تقسیم را فراهم میکند. اما معیار Sales All Colors باید مقدار Sales Amount را در فیلتر کانتکست هدف ارزیابی کند.
حذف یک فیلتر
با مقایسهی دو فیلتر کانتکست، میتوانیم فیلتر کانتکست اولیه (برای صورت کسر) را طوری تغییر دهیم که به فیلتر کانتکست هدف (برای مخرج) برسیم و بتوانیم معیار مورد نیاز را محاسبه کنیم.
برای مثال، معیار % of Color فیلتر کانتکستی دارد که متناظر با صورت کسر است. این فیلتر کانتکست شامل سه فیلتر است:
رنگ Blue
برند Contoso
کشورها: Canada و United States
اما فیلتر کانتکست هدف که برای Sales All Colors لازم است، تنها شامل دو فیلتر است:
برند Contoso
کشورها: Canada و United States
تفاوت این دو فیلتر کانتکست فقط در فیلتر رنگ (Color) است که در فیلتر کانتکست هدف وجود ندارد.
برای رسیدن به فیلتر کانتکست هدف برای معیار Sales All Colors، باید فیلتر رنگ را از فیلتر کانتکست اولیه حذف کنیم.
برای این کار، از تابع CALCULATE
استفاده میکنیم:
ابتدا فیلتر کانتکست اولیه (که مربوط به صورت کسر است) بهطور موقت کپی میشود،
سپس تابع
REMOVEFILTERS
، فیلتر مربوط بهProduct[Color]
را حذف میکند،در نهایت، معیار Sales Amount در این فیلتر کانتکست اصلاحشده (یعنی مخرج کسر) ارزیابی میشود.

این هم تعریف مژر Sales All Colors است:

ما همچنین میتوانیم به جای REMOVEFILTERS
از تابع ALL
استفاده کنیم — رفتار این دو در داخل CALCULATE
یکسان است. اما ما استفاده از REMOVEFILTERS
را ترجیح میدهیم، چون از نظر معنایی، بهتر بیان میکند که دقیقاً چه عملی در فیلتر کانتکست انجام میشود: فیلتر حذف میشود، نه اینکه با لیستی از تمام مقادیر موجود در ستون جایگزین شود.
افزودن یک فیلتر
قبلاً دیدیم که چگونه میتوان یک فیلتر را حذف کرد تا به فیلتر کانتکست هدف برسیم. اما در برخی موارد، لازم است فیلتری را اضافه کنیم که در فیلتر کانتکست اولیه وجود ندارد.
به خاطر داشته باش: افزودن یک فیلتر معمولاً باعث کاهش تعداد سطرهایی میشود که در عملیات تجمیع لحاظ میگردند، بنابراین نتیجهی نهایی کمتر خواهد بود. این موضوع ممکن است در ابتدا کمی ضد شهود بهنظر برسد، چون داریم «فیلتر اضافه میکنیم» اما «نتیجه را کاهش میدهیم»!
برای مثال، فرض کن میخواهیم مقدار فروش (Sales Amount) هر رنگ محصول را با فروش متناظر محصولات برند Contoso مقایسه کنیم. برای این کار باید معیاری به نام Sales Contoso پیادهسازی کنیم.
در این حالت، فیلتر کانتکست اولیه برای Sales Amount فقط فیلتر رنگ (Color) را دارد. حالا برای محاسبهی Sales Contoso، فقط کافی است با استفاده از CALCULATE
یک فیلتر برای Product[Brand]
اضافه کنیم.

اگرچه شرط فیلتر بهصورت یک عبارت (expression) نوشته میشود، اما چیزی که در فیلتر کانتکست هدف بهدست میآید، یک جدول است که شامل لیستی از مقادیر فیلترشده در ستون Brand میباشد — که در این مثال، فقط مقدار Contoso است.

تا زمانی که فیلتری که به filter context اعمال میشود، مربوط به ستونهایی باشد که بهطور مستقیم توسط فیلتر کانتکست اولیه فیلتر نشدهاند، آن شرط فیلتر صرفاً یک فیلتر جدید اضافه میکند.
اما اگر فیلتری از قبل وجود داشته باشد، باید به دقت توجه کنیم، چون ممکن است فیلتر جدید فیلتر قبلی را حذف یا جایگزین کند.
جایگزینی یک فیلتر
یک سناریوی متفاوت، جایگزینی یک فیلتر موجود در filter context با فیلتری دیگر است.
برای مثال، در گزارش زیر میخواهیم فروش هر کشور در سالهای مختلف را با فروش در سال ۲۰۱۷ مقایسه کنیم و از آن به عنوان مبنای مقایسه (Benchmark) استفاده کنیم.
معیار Benchmark 2017 مقدار فروش سال جاری را بر فروش سال ۲۰۱۷ تقسیم میکند.
مشابه مثالی که قبلاً دیدیم، میتوانیم این معیار را بهصورت تقسیم بین دو معیار بنویسیم:

وقتی فیلتر کانتکست اولیه (صورت کسر) را با فیلتر کانتکست هدف (مخرج) مقایسه میکنیم، متوجه میشویم که باید فیلتر موجود بر روی سال (Year) را با سال ۲۰۱۷ جایگزین کنیم.

نحو (Syntax) تابع CALCULATE به طرز جالبی مشابه نحو (Syntax) مثالی است که قبلاً دیدیم، زمانی که یک فیلتر را به فیلتر کانتکست اضافه کردیم:

در واقع، آرگومان فیلتر در تابع CALCULATE، فیلتر مربوط به سال (۲۰۱۷) را به فیلتر کانتکست اولیه اضافه میکند. با این حال، فیلتر موجود روی سال (برای مثال، ۲۰۱۸) حذف میشود، زیرا هر فیلتر جدیدی که به فیلتر کانتکست اضافه میشود، بهطور خودکار هر فیلتر موجود بر روی ستونهای مربوطه را حذف میکند.

از منظر DAX، مانند این است که بگوییم هر بار که فیلتری به فیلتر کانتکست اضافه میکنید، بهطور خودکار یک REMOVEFILTERS
روی همان ستونها به همان تابع CALCULATE اضافه میشود. بنابراین، نتیجهای که بهدست میآید مشابه این خواهد بود که کد زیر را نوشته باشیم:

ترکیب یک فیلتر جدید با فیلترهای موجود
حذف خودکار فیلتر موجود در مثال قبلی مفید بود، اما ممکن است بخواهیم این رفتار را زمانی که نیازهای متفاوتی داریم، تغییر دهیم.
برای مثال، فرض کن که باید معیاری به نام Large Transactions ایجاد کنیم که مقدار فروش (Sales Amount) برای معاملاتی که مقدار آنها بیشتر از ۱۰۰۰ است را برگرداند. این شرط فیلتر باید نتیجه ضرب دو ستون فروش (تعداد کالا و قیمت خالص) را فیلتر کند، که نتیجهی آن یک فیلتر با دو ستون است و نه فقط یک ستون.
با این حال، اگر در گزارش قبلاً فیلترهایی روی تعداد کالا (Quantity) یا قیمت خالص (Net Price) اعمال شده باشد، ما نمیخواهیم که این فیلترها در محاسبهمان حذف شوند.
راهحل این است که شرط فیلتر را در داخل تابع KEEPFILTERS
قرار دهیم:

ما میتوانیم نحوهی عملکرد این محاسبه را گام به گام مشاهده کنیم، همراه با تصاویری از تغییرات اعمالشده در فیلتر کانتکست.

فیلتر کانتکست اولیه برای مقدار فروش (Sales Amount) محصولات Contoso فقط شامل دو فیلتر است: Brand (Contoso) و Net Price. شرط Sales[Quantity] * Sales[Net Price] > 1000 در تابع CALCULATE، یک فیلتر با دو ستون (تعداد کالا و قیمت خالص) به فیلتر کانتکست اضافه میکند. حضور تابع KEEPFILTERS از حذف فیلتر موجود روی Net Price جلوگیری میکند، که در غیر این صورت توسط فیلتر جدید حذف میشد. اگر به اطلاعات بیشتری درباره استفاده از KEEPFILTERS
نیاز داری، باید بهترین شیوهها را در مقاله قبلی مطالعه کنی.
استفاده از نمایش گرافیکی فیلتر کانتکست برای هر دو مورد مفید است: هم برای برنامهریزی پیادهسازی یک محاسبه با استفاده از CALCULATE و هم برای توضیح رفتار محاسبات موجود.
در حالی که موتور محاسباتی ممکن است از بهینهسازیها برای جلوگیری از مادیسازی واقعی هر فیلتر استفاده کند، این روش نمایشی از فیلترها در فیلتر کانتکست میتواند هر مورد خاص از دستکاری فیلتر کانتکست را توضیح دهد.
شما میتوانید فیلترها را در فیلتر کانتکست با استفاده از CALCULATE حذف، اضافه و جایگزین کنید. هدف از این مقاله، ارائه یک دیدگاه دیگر درباره فیلتر کانتکست است، بدون اینکه مطالب موجود در مقالات، کتابها و دورههای ویدیویی دیگر را جایگزین کند. علاوه بر این، هیچ راهی بهتر از تمرین کردن روی دادههای خودتان برای یادگیری وجود ندارد. اگر شما یک یادگیرنده بصری هستید، امیدواریم این مقاله به شما کمک کند، زیرا دیدگاه اضافی برای نمایش مفاهیم انتزاعی پشت Evaluation Context در DAX را فراهم میکند.
دیدگاهتان را بنویسید