در طراحی Measureهای پیشرفته DAX، یکی از نیازهای همیشگی، کنترل دقیق روی اینکه کدام فیلترها باید در یک محاسبه حذف شوند و کدام باقی بمانند، است. پیش از معرفی REMOVEFILTERS، یکی از رایجترین ابزارها برای حذف فیلتر در DAX، تابع ALL بود. با این حال، ALL علاوه بر حذف فیلتر، قابلیت استفاده بهعنوان Table Expression را نیز دارد و همین موضوع گاهی باعث ابهام در خوانایی Measure میشد.
REMOVEFILTERS برای بیان صریح عملیات حذف فیلتر در DAX ارائه شده است. برخلاف ALL که هم برای حذف فیلتر و هم برای برگرداندن یک Table Expression کاربرد دارد، REMOVEFILTERS فقط برای تغییر Filter Context از طریق حذف فیلتر طراحی شده است.
در این مقاله بررسی میکنیم REMOVEFILTERS دقیقاً چه کاری انجام میدهد، چه تفاوتی با ALL و ALLEXCEPT دارد، چگونه در ترکیب با CALCULATE و CALCULATETABLE به کار میرود، در چه سناریوهای سازمانی کاربرد دارد و چه نکاتی از منظر Performance و خوانایی کد باید در پروژههای Power BI رعایت شود.
تعریف REMOVEFILTERS و ساختار پایه آن
REMOVEFILTERS یک Filter Modifier است و خودش Table Expression برنمیگرداند. بنابراین برای تغییر Filter Context در محاسباتی مانند CALCULATE و CALCULATETABLE استفاده میشود و نمیتوان خروجی آن را مستقیماً بهعنوان یک جدول به توابعی مانند COUNTROWS یا SUMX داد.
ساختار کلی این تابع به دو شکل ممکن است نوشته شود.
REMOVEFILTERS ( )
REMOVEFILTERS ( <TableOrColumn>, [<Column2>], ... )
اگر بدون هیچ آرگومانی فراخوانی شود، تمام فیلترهای موجود در کل مدل داده حذف میشوند. اگر با یک جدول فراخوانی شود، تمام فیلترهای آن جدول حذف میشوند. اگر با یک یا چند ستون مشخص فراخوانی شود، تنها فیلترهای همان ستونها حذف میشوند و سایر فیلترها دستنخورده باقی میمانند.
Sales Without Product Name =
CALCULATE (
[Total Sales],
REMOVEFILTERS ( Product[ProductName] )
)
اینجا فقط ProductName از Filter Context حذف میشود.
Sales Without Product Filters =
CALCULATE (
[Total Sales],
REMOVEFILTERS ( Product )
)
Product حذف میشوند.بنابراین انتخاب بین REMOVEFILTERS(Column) و REMOVEFILTERS(Table) فقط یک تفاوت Syntax نیست، بلکه تعیین میکند چه بخشی از Filter Context تغییر کند.
حذف فیلتر از یک ستون مشخص
فرض کنید در یک مدل فروش سازمانی، Measure پایه فروش کل را داریم.
Total Sales =
SUM ( Sales[Amount] )
برای محاسبه سهم فروش هر محصول از کل فروش، صرفنظر از اینکه کاربر روی کدام محصول فیلتر کرده، میتوان از REMOVEFILTERS استفاده کرد.
Sales Percentage =
DIVIDE (
[Total Sales],
CALCULATE (
[Total Sales],
REMOVEFILTERS ( Product[ProductName] )
)
)
در این Measure، بخش اول کسر فروش محصول جاری را محاسبه میکند و بخش دوم، با حذف فیلتر ستون ProductName، فروش کل بدون محدودیت محصول را برمیگرداند. نتیجه، درصد سهم هر محصول از فروش کل است.
مسیر اجرای داخلی REMOVEFILTERS
Current Filter Context
Product = لپتاپ پرو
│
▼
CALCULATE اجرا میشود
│
▼
REMOVEFILTERS ( Product[ProductName] )
│
▼
حذف فیلتر ستون ProductName
│
▼
Filter Context جدید: بدون فیلتر محصول
│
▼
Total Sales در Context جدید محاسبه میشود
تفاوت REMOVEFILTERS با ALL
از نظر نتیجه نهایی، در بسیاری از سناریوهای ساده، REMOVEFILTERS و ALL رفتار یکسانی تولید میکنند.
با ALL:
CALCULATE (
[Total Sales],
ALL ( Product[ProductName] )
)
با REMOVEFILTERS:
CALCULATE (
[Total Sales],
REMOVEFILTERS ( Product[ProductName] )
)
هر دو فیلتر ستون ProductName را حذف میکنند و در این مثال ساده، خروجی یکسانی تولید میکنند. اما تفاوت مفهومی مهمی بین این دو وجود دارد که در سناریوهای پیچیدهتر خودش را نشان میدهد.
ALL در برخی فرمهای خود مانند ALL(Table) و ALL(Column) علاوه بر نقش Filter Modifier، یک Table Expression نیز برمیگرداند. در مقابل، REMOVEFILTERS صرفاً برای حذف فیلتر طراحی شده و مقدار جدولی برنمیگرداند.
Distinct Product Count =
COUNTROWS ( ALL ( Product[ProductName] ) )
REMOVEFILTERS چنین قابلیتی ندارد و تنها در جایگاه آرگومان فیلتر CALCULATE یا CALCULATETABLE معنا دارد. تلاش برای استفاده از آن در جایی مانند COUNTROWS به همان شکلی که ALL استفاده میشود، از نظر Syntax پشتیبانی نمیشود.
نامعتبر:
COUNTROWS ( REMOVEFILTERS ( Product[ProductName] ) )
این محدودیت در واقع یک ویژگی طراحی است، نه نقص. از آنجا که REMOVEFILTERS تنها یک هدف دارد، یعنی حذف فیلتر، خواننده کد با دیدن نام این تابع بلافاصله متوجه میشود هدف آن خط، تغییر Filter Context است، نه ساخت یک جدول برای مصرف در جای دیگر. این شفافیت نیت، مزیت اصلی REMOVEFILTERS نسبت به ALL در نگارش Measureهای جدید محسوب میشود.
تفاوت REMOVEFILTERS با ALLEXCEPT
ALLEXCEPT برای سناریویی طراحی شده که باید تقریباً تمام فیلترهای یک جدول حذف شوند، بهجز چند ستون مشخص که باید حفظ شوند.
Sales By Year =
CALCULATE (
[Total Sales],
ALLEXCEPT (
'Date',
'Date'[Year]
)
)
در این مثال، ALLEXCEPT فیلترهای Context اعمالشده روی جدول Date را حذف میکند، بهجز فیلتری که روی ستون Year حفظ میشود. بنابراین اگر جدول Date از طریق ستونهایی مانند Month، Quarter یا MonthName فیلتر شده باشد، این فیلترها حذف میشوند اما فیلتر Year همچنان در محاسبه باقی میماند.
میتوان همین منطق را با REMOVEFILTERS نیز بازنویسی کرد، اما این کار نیازمند فهرست کردن صریح تمام ستونهایی است که باید فیلترشان حذف شود، که در جداول با تعداد ستون زیاد، عملی نیست. REMOVEFILTERS برای حذف فیلتر از ستونهای مشخص و معدود طراحی شده، نه برای سناریوی معکوس ALLEXCEPT که هدف آن نگه داشتن چند ستون خاص و حذف باقی است.
نکتهای که در انتخاب بین این دو باید در نظر گرفت این است که ALLEXCEPT تمام فیلترهای جدول را بهجز ستونهای مشخصشده حذف میکند، بنابراین اگر در آینده فیلتر جدیدی روی همان جدول اضافه شود، این فیلتر نیز بهطور ناخواسته توسط ALLEXCEPT حذف خواهد شد. در بسیاری از مدلها، اگر هدف واقعی صرفاً حذف فیلتر یک یا دو ستون مشخص است، نه نگه داشتن یک ستون در برابر همه فیلترهای احتمالی آینده، فهرستکردن صریح همان ستونها با REMOVEFILTERS کنترل قابلپیشبینیتری نسبت به ALLEXCEPT ارائه میدهد.
با REMOVEFILTERS برای هدف مشخص:
CALCULATE (
[Total Sales],
REMOVEFILTERS ( Product ),
REMOVEFILTERS ( Customer[Segment] )
)
در این نسخه، دقیقاً مشخص است که فیلتر جدول Product و فیلتر ستون Segment از جدول Customer حذف میشوند و هیچ رفتار ضمنی یا وابسته به ساختار آینده مدل وجود ندارد.
استفاده از REMOVEFILTERS بدون آرگومان
یکی از کاربردهای مهم REMOVEFILTERS، استفاده از آن بدون آرگومان برای حذف تمام فیلترهای فعال در مدل است.
Grand Total Sales =
CALCULATE (
[Total Sales],
REMOVEFILTERS ()
)
این Measure، فروش کل را بدون در نظر گرفتن فیلترهای فعال در Filter Context محاسبه میکند و برای ساخت شاخصهای مرجع که باید مستقل از فیلترهای گزارش باشند، کاربرد دارد.
Sales Share of Total =
DIVIDE (
[Total Sales],
CALCULATE (
[Total Sales],
REMOVEFILTERS ()
)
)
نکته مهم این است که REMOVEFILTERS در این رفتار تنها نیست. ALL نیز میتواند بدون آرگومان برای حذف تمام فیلترها استفاده شود.
CALCULATE (
[Total Sales],
ALL ()
)
بنابراین مزیت اصلی استفاده از REMOVEFILTERS() در اینجا، تفاوت عملکردی با ALL() نیست، بلکه بیان صریحتر نیت Measure است. نام REMOVEFILTERS برای خواننده بهروشنی مشخص میکند که هدف این بخش از محاسبه، حذف فیلترهاست، در حالی که ALL در DAX علاوه بر نقش Filter Modifier، قابلیت بازگرداندن یک Table Expression را نیز دارد.
به همین دلیل، در Measureهای جدیدی که هدف صرفاً حذف فیلتر است، REMOVEFILTERS() معمولاً انتخاب خواناتری محسوب میشود.
ترکیب REMOVEFILTERS با KEEPFILTERS
از آنجا که REMOVEFILTERS فیلتر را حذف میکند و KEEPFILTERS مانع جایگزینی فیلتر موجود توسط فیلتر جدید میشود، این دو تابع در دو سطح متفاوت عمل میکنند و میتوانند در یک Measure واحد برای کنترل دقیق چند بخش مختلف از Filter Context به کار روند.
Regional Sales Fixed Category =
CALCULATE (
[Total Sales],
REMOVEFILTERS ( Product[Category] ),
KEEPFILTERS ( Customer[Region] = "North" )
)
در این Measure، فیلتر دستهبندی محصول بهطور کامل حذف میشود، در حالی که فیلتر منطقه بهجای جایگزینی، با فیلتر موجود روی همان ستون ترکیب میشود. این ترکیب در گزارشهایی که نیاز به کنترل همزمان چند بعد مختلف با رفتارهای متفاوت دارند، اهمیت زیادی دارد.
کاربرد سازمانی: محاسبه شاخصهای مقایسهای با پایه ثابت
یکی از رایجترین کاربردهای REMOVEFILTERS در پروژههای سازمانی، ساخت شاخصهایی است که باید نسبت به یک پایه ثابت، مستقل از فیلترهای کاربر، مقایسه شوند.
Product Share Within Category =
DIVIDE (
[Total Sales],
CALCULATE (
[Total Sales],
REMOVEFILTERS ( Product[ProductName] )
)
)
این Measure سهم هر محصول را در میان محصولات همان دستهبندی که در Context فعلی فیلتر شده محاسبه میکند، زیرا تنها فیلتر ProductName حذف شده و فیلتر Category، در صورت وجود، دستنخورده باقی میماند. این رفتار دقیقاً مطلوب سناریوهایی است که باید سهم یک آیتم را در محدوده گروه فعلی، نه در کل مدل، محاسبه کرد.
تأثیر REMOVEFILTERS بر Performance
از منظر Performance، در سناریوهایی که REMOVEFILTERS و ALL صرفاً برای حذف فیلتر در CALCULATE استفاده میشوند، معمولاً تفاوت محسوسی در هزینه اجرایی ایجاد نمیشود و انتخاب بین آنها بیشتر به خوانایی کد و نیاز به Table Expression بستگی دارد.
هزینه اصلی Measure معمولاً به حجم داده، تعداد محاسبات، پیچیدگی Filter Context، روابط مدل و نحوه اجرای Expression وابسته است. بنابراین نباید صرفاً با تغییر ALL به REMOVEFILTERS انتظار بهبود قابل توجه Performance داشت.
برای بررسی رفتار واقعی یک Measure در مدل سازمانی، بهتر است از ابزارهایی مانند DAX Studio، Server Timings و Query Plan استفاده شود.
اشتباهات رایج در استفاده از REMOVEFILTERS
تلاش برای استفاده از REMOVEFILTERS بهعنوان Table Expression
یکی از رایجترین اشتباهات، تلاش برای استفاده از REMOVEFILTERS در جایگاهی است که یک جدول واقعی موردنیاز است، مانند ورودی SUMX یا COUNTROWS، درست به همان شکلی که ALL استفاده میشود. از آنجا که REMOVEFILTERS چنین قابلیتی ندارد، این تلاش با خطای Syntax مواجه میشود و باید در چنین سناریوهایی از ALL استفاده کرد.
فراموش کردن اینکه REMOVEFILTERS فقط ستونهای مشخصشده را تحت تأثیر قرار میدهد
مشابه ALL روی یک ستون، REMOVEFILTERS نیز تنها همان ستون یا جدولی را که بهصراحت در آرگومان آن ذکر شده تحت تأثیر قرار میدهد. تصور اینکه REMOVEFILTERS روی یک ستون، باعث حذف تمام فیلترهای جدول والد آن ستون میشود، اشتباه رایجی است که میتواند نتیجهای متفاوت از انتظار تولید کند.
استفاده از ALLEXCEPT در جایی که REMOVEFILTERS کنترل بهتری ارائه میدهد
در سناریوهایی که هدف صرفاً حذف فیلتر یک یا چند ستون مشخص است، نه نگه داشتن یک ستون در برابر تمام فیلترهای احتمالی آینده روی سایر ستونهای جدول، استفاده از ALLEXCEPT میتواند رفتار غیرمنتظرهای در مواجهه با فیلترهای جدیدی که بعداً به مدل اضافه میشوند ایجاد کند. در چنین شرایطی، فهرستکردن صریح ستونها با REMOVEFILTERS کنترل قابلپیشبینیتری فراهم میکند.
Best Practiceهای استفاده از REMOVEFILTERS در پروژههای سازمانی
در Measureهای جدید که هدف صرفاً حذف فیلتر از یک ستون یا جدول مشخص است، بدون نیاز به استفاده از همان Expression بهعنوان جدول ورودی برای Iteratorها، REMOVEFILTERS به دلیل بیان صریحتر نیت، انتخاب خواناتری نسبت به ALL است.
اگر همان جدول یا ستون فیلترشده باید در جای دیگری از همان Measure نیز بهعنوان یک Table Expression مستقل استفاده شود، مانند ورودی SUMX یا COUNTROWS، باید از ALL استفاده کرد، زیرا REMOVEFILTERS چنین قابلیتی ندارد.
پیش از استفاده از ALLEXCEPT برای حذف فیلتر همه ستونهای یک جدول بهجز چند مورد، باید بررسی شود که آیا فهرستکردن صریح ستونهای موردنظر با REMOVEFILTERS، به دلیل کنترل بیشتر روی رفتار آینده مدل، انتخاب مناسبتری نیست.
در Measureهای مرجع که باید مستقل از تمام فیلترهای گزارش محاسبه شوند، استفاده از REMOVEFILTERS بدون آرگومان، جایگزین سادهتری نسبت به فراخوانی جداگانه ALL روی تمام جداول مدل است.
مستندسازی هدف استفاده از REMOVEFILTERS در کامنت Measure، بهخصوص در Measureهای پیچیدهتر که چند بار از این تابع در کنار KEEPFILTERS استفاده میشود، برای تیم توسعه بعدی که ممکن است منطق را تغییر دهد، ارزش نگهداری بالایی دارد.
| نیاز | تابع پیشنهادی |
|---|---|
| حذف فیلتر یک ستون | REMOVEFILTERS(Column) |
| حذف فیلتر چند ستون | REMOVEFILTERS(Column1, Column2) |
| حذف فیلتر یک جدول | REMOVEFILTERS(Table) |
| نیاز به Table Expression بدون فیلتر | ALL(Table) |
| نیاز به جدول بدون فیلتر | ALL(Table) |
| حفظ چند ستون و حذف بقیه | ALLEXCEPT() |
| حفظ فیلتر موجود هنگام افزودن فیلتر جدید | KEEPFILTERS() |
جمعبندی
REMOVEFILTERS تابعی است که با یک هدف مشخص و بدون نقش اضافه، برای حذف فیلتر از یک جدول یا ستون در DAX طراحی شده است. برخلاف ALL که هم میتواند حذف فیلتر انجام دهد و هم بهعنوان یک Table Expression مستقل عمل کند، REMOVEFILTERS تنها در جایگاه آرگومان فیلتر CALCULATE و CALCULATETABLE معنا دارد و همین محدودیت طراحیشده، خوانایی و شفافیت نیت را در Measureهای پیچیده افزایش میدهد.
از منظر Performance، انتخاب بین REMOVEFILTERS و ALL برای حذف فیلتر ساده معمولاً تفاوت محسوسی ایجاد نمیکند و باید بر اساس نیاز واقعی به قابلیت Table Expression تصمیمگیری شود، نه صرفاً بر اساس عملکرد اجرایی. در مقابل، در مقایسه با ALLEXCEPT، REMOVEFILTERS با فهرستکردن صریح ستونهای موردنظر، کنترل قابلپیشبینیتری در برابر تغییرات آینده مدل فراهم میکند.
پیشنهاد مطالعه
- مرجع زبان DAX افزونه کوئری نویسی در اکسل و POWER BI
- مرجع زبان فرمول نویسی M در پاور کوئری
- طراحی داشبوردهای مدیریتی در Microsoft Power BI
سوالات متداول FAQ
آیا REMOVEFILTERS دقیقاً همان کار ALL را انجام میدهد؟
از نظر حذف فیلتر، در سناریوهای ساده، بله رفتار مشابهی دارند. اما ALL علاوه بر حذف فیلتر، یک Table Expression مستقل نیز محسوب میشود که میتواند در جاهایی مانند COUNTROWS یا SUMX استفاده شود، در حالی که REMOVEFILTERS چنین قابلیتی ندارد و فقط در آرگومان فیلتر CALCULATE یا CALCULATETABLE کاربرد دارد.
چه زمانی REMOVEFILTERS بهتر از ALLEXCEPT است؟
زمانی که هدف فقط حذف فیلتر از یک یا چند ستون یا یک جدول مشخص باشد، REMOVEFILTERS معمولاً انتخاب خواناتری است، زیرا دقیقاً همان چیزی را که باید حذف شود مشخص میکند. ALLEXCEPT زمانی مناسبتر است که هدف حفظ فیلتر چند ستون مشخص و حذف سایر فیلترهای همان جدول باشد.
آیا REMOVEFILTERS بدون آرگومان معنای خاصی دارد؟
بله. REMOVEFILTERS بدون هیچ آرگومان، تمام فیلترهای فعال در کل مدل را حذف میکند و برای ساخت Measureهای مرجع، مانند مجموع کل فروش سازمان صرفنظر از هر فیلتری در گزارش، کاربرد دارد.
چرا نمیتوان REMOVEFILTERS را در COUNTROWS بهجای ALL استفاده کرد؟
زیرا REMOVEFILTERS یک Table Expression مستقل نیست و تنها در جایگاه آرگومان فیلتر CALCULATE یا CALCULATETABLE قابل استفاده است. برای سناریوهایی که به یک جدول واقعی برای پیمایش یا شمارش نیاز است، باید از ALL استفاده کرد.
آیا REMOVEFILTERS از نظر Performance بهتر از ALL است؟
معمولاً خیر. تفاوت اصلی این دو تابع مفهومی و مربوط به خوانایی و نقش آنها در کد است، نه هزینه اجرایی. انتخاب بین آنها باید بر اساس نیاز واقعی به قابلیت Table Expression انجام شود.
مشاوره تخصصی Power BI و DAX برای سازمانها
اگر Measureهای Power BI شما با Filter Contextهای پیچیده، محاسبات مقایسهای، KPIهای مدیریتی یا مشکلات Performance مواجه هستند، طراحی صحیح DAX میتواند تفاوت قابل توجهی در دقت و سرعت گزارشها ایجاد کند.
تیم توسعه فناوری اطلاعات لاندا در طراحی مدلهای Power BI، توسعه Measureهای پیشرفته DAX، بهینهسازی Performance و تحلیل مشکلات محاسباتی به سازمانها کمک میکند.
اگر در مدل Power BI خود با محاسبات پیچیده، Measureهای کند یا نتایج غیرمنتظره در Filter Context مواجه هستید، میتوانید برای بررسی و بهینهسازی مدل با لاندا در ارتباط ✆ باشید.


No comment