در تقریباً هر مدل تحلیلی Power BI، دیر یا زود به محاسباتی میرسیم که مبتنی بر تقسیم هستند: نرخ رشد، درصد از کل، حاشیه سود، میانگین هر تراکنش و دهها شاخص مدیریتی دیگر. مشکلی که در همان قدم اول با آن روبهرو میشویم این است که مخرج کسر، در بسیاری از سطرهای Filter Context، میتواند صفر یا BLANK باشد. یک محصول بدون فروش سال قبل، یک منطقه بدون بودجه تعریفشده یا یک مشتری بدون تراکنش، همگی میتوانند باعث شوند مخرج یک محاسبه تقسیمی صفر شود.
اگر این تقسیم با عملگر معمولی / نوشته شود و مخرج در یک Filter Context برابر صفر باشد، DAX ممکن است نتیجهای مانند Infinity تولید کند و در حالت 0 / 0 مقدار NaN به دست آید. این نتایج معمولاً برای نمایش در گزارشهای مدیریتی مناسب نیستند. تابع DIVIDE برای مدیریت همین شرایط طراحی شده است و در صورت صفر یا BLANK بودن مخرج، بهجای این نتایج، BLANK() یا مقدار جایگزین تعیینشده را برمیگرداند.
در این مقاله بررسی میکنیم DIVIDE دقیقاً چگونه کار میکند، چه تفاوتی با عملگر تقسیم معمولی دارد، پارامتر سوم آن چه نقشی ایفا میکند و چه محدودیتی دارد، در چه سناریوهای رایج مدیریتی کاربرد دارد، چه اشتباهاتی در استفاده از آن رایج است و چه نکاتی از منظر Performance باید در مدلهای سازمانی حجیم رعایت شود.
تعریف DIVIDE و ساختار پایه آن
DIVIDE تابعی است که یک عملیات تقسیم را بین صورت و مخرج انجام میدهد، اما برخلاف عملگر تقسیم معمولی، در برابر مخرج صفر یا BLANK بهجای تولید مقادیر نامطلوب، یک مقدار جایگزین از پیش تعیینشده بازمیگرداند. ساختار کلی این تابع به شکل زیر است.
DIVIDE ( <Numerator>, <Denominator>, <AlternateResult> )
پارامتر اول صورت کسر است، پارامتر دوم مخرج کسر است و پارامتر سوم که اختیاری است، مقداری را مشخص میکند که در صورت صفر یا BLANK بودن مخرج بازگردانده شود. اگر پارامتر سوم مشخص نشود، مقدار پیشفرض آن BLANK خواهد بود.
مثال پایه: مقایسه DIVIDE با عملگر تقسیم معمولی
فرض کنید در یک مدل فروش سازمانی، دو Measure زیر را داریم.
Total Sales =
SUM ( Sales[Amount] )
Total Budget =
SUM ( Budget[Amount] )
اگر بخواهیم درصد تحقق بودجه را با عملگر تقسیم معمولی محاسبه کنیم.
Budget Achievement Ratio =
[Total Sales] / [Total Budget]
این Measure در بیشتر سطرهای گزارش بهدرستی کار میکند، اما به محض آنکه در یک سطر خاص، مثلاً یک منطقه جدید که هنوز بودجهای برای آن تعریف نشده، مقدار Total Budget برابر صفر یا BLANK باشد، این عملیات میتواند خروجی نامطلوبی مانند Infinity تولید کند که برای نمایش در گزارش مناسب نیست.
با استفاده از DIVIDE، همین محاسبه به شکل امن بازنویسی میشود.
Budget Achievement Ratio =
DIVIDE (
[Total Sales],
[Total Budget]
)
در این حالت، اگر Total Budget برابر صفر یا BLANK باشد، بهجای تولید یک مقدار نامعتبر، خروجی Measure بهصورت پیشفرض BLANK خواهد بود و Visual آن سطر یا سلول را بهسادگی خالی نمایش میدهد.
مسیر اجرای داخلی DIVIDE
دریافت صورت و مخرج
│
▼
بررسی مقدار مخرج
│
├─────── مخرج صفر یا BLANK است
│ │
│ ▼
│ بازگرداندن مقدار جایگزین
│ (پیشفرض BLANK)
│
└── مخرج مقدار معتبر دارد
│
▼
انجام تقسیم معمولی
│
▼
بازگرداندن نتیجه تقسیم
استفاده از پارامتر سوم برای تعیین مقدار جایگزین
در بسیاری از گزارشهای مدیریتی، نمایش BLANK کافی نیست و نیاز داریم مقدار جایگزینی معنادارتر، مانند صفر، نمایش داده شود. این دقیقاً همان هدفی است که پارامتر سوم DIVIDE برای آن طراحی شده است.
Budget Achievement Ratio =
DIVIDE (
[Total Sales],
[Total Budget],
0
)
در این نسخه، اگر Total Budget صفر یا BLANK باشد، بهجای BLANK، مقدار عددی صفر بازگردانده میشود. این تفاوت بهظاهر کوچک، در عمل تأثیر زیادی روی رفتار Visualها دارد. در بسیاری از Visualهای Power BI، گروههایی که مقدار Measure آنها BLANK است بهصورت پیشفرض از نمایش حذف میشوند. به همین دلیل، حفظ BLANK معمولاً باعث میشود Visual روی گروههایی تمرکز کند که واقعاً داده دارند. در صورت نیاز میتوان با گزینه Show items with no data گروههای بدون داده را نیز نمایش داد.
انتخاب بین BLANK و صفر بهعنوان مقدار جایگزین باید بر اساس معنای واقعی گزارش انجام شود. اگر عدم وجود بودجه به معنای «این داده اصلاً وجود ندارد» است، BLANK انتخاب مناسبتری است. اگر عدم وجود بودجه باید بهصورت «تحقق صفر درصد» تفسیر شود، صفر منطقیتر است. در برخی گزارشهای خاص، حتی میتوان یک مقدار عددی نشانگر مانند منفی یک را بهعنوان مقدار جایگزین بازگرداند تا در مراحل بعدی پردازش، این سطرها بهراحتی قابل شناسایی باشند.
Budget Status Flag =
DIVIDE (
[Total Sales],
[Total Budget],
-1
)
استفاده از مقادیری مانند منفی یک فقط زمانی منطقی است که این مقدار بهعنوان یک کد یا Flag در منطق مدل تعریف شده باشد. برای Measureهای تحلیلی که قرار است بهعنوان Ratio یا Percentage نمایش داده شوند، معمولاً BLANK یا صفر انتخابهای معنادارتری هستند.
یک نکته مهم درباره پارامتر سوم DIVIDE این است که AlternateResult باید یک مقدار ثابت باشد. بنابراین نمیتوان یک Measure یا Expression محاسباتی را مستقیماً بهعنوان نتیجه جایگزین این پارامتر قرار داد. اگر نتیجه جایگزین باید بر اساس منطق دیگری بهصورت پویا محاسبه شود، باید منطق مربوطه را خارج از DIVIDE و معمولاً با استفاده از IF یا ساختارهای شرطی دیگر پیادهسازی کرد.
با محاسبه پویای مقدار جایگزین:
Budget Achievement Ratio Dynamic =
VAR Ratio = DIVIDE ( [Total Sales], [Total Budget] )
RETURN
IF (
ISBLANK ( Ratio ),
[Default Fallback Value],
Ratio
)
DIVIDE بهعنوان جایگزین امن برای عملگر تقسیم در محاسبات پرکاربرد
سناریوهای رایج زیر، نمونههایی از محاسباتی هستند که در پروژههای سازمانی تقریباً همیشه با DIVIDE نوشته میشوند، نه با عملگر تقسیم معمولی.
محاسبه میانگین ارزش هر تراکنش
Average Order Value =
DIVIDE (
[Total Sales],
[Total Orders]
)
اگر در یک بازه زمانی یا برای یک مشتری خاص هیچ سفارشی ثبت نشده باشد، Total Orders برابر صفر یا BLANK خواهد بود. بدون DIVIDE، این محاسبه در چنین سطرهایی میتوانست نتیجهای نامعتبر تولید کند.
محاسبه نرخ رشد سالانه
YoY Growth =
DIVIDE (
[Total Sales] - [Previous Year Sales],
[Previous Year Sales]
)
در اولین سالی که یک محصول جدید به فروش میرسد، مقدار Previous Year Sales طبیعتاً BLANK خواهد بود. استفاده از DIVIDE در این حالت باعث میشود Measure بهجای یک نتیجه نامعتبر، مقدار BLANK را نمایش دهد که از نظر تحلیلی نیز صحیح است، زیرا نرخ رشد برای محصولی که سال قبل اصلاً وجود نداشته، از نظر مفهومی قابل تعریف نیست.
محاسبه درصد از کل
Percentage of Total =
DIVIDE (
[Product Sales],
CALCULATE ( [Total Sales], ALL ( Product ) )
)
اگر در یک Context خاص، به هر دلیلی مخرج این کسر صفر شود، DIVIDE از تولید یک نتیجه نامطلوب در سطح کل Visual جلوگیری میکند.
تفاوت رفتار DIVIDE در برابر BLANK و صفر در صورت کسر
نکتهای که گاهی نادیده گرفته میشود این است که رفتار خاص DIVIDE فقط به مقدار مخرج بستگی دارد، نه صورت. اگر صورت کسر BLANK باشد اما مخرج مقدار معتبری داشته باشد، DIVIDE مانند یک تقسیم معمولی عمل میکند و نتیجه آن BLANK یا صفر، بسته به نحوه تفسیر BLANK در عملیات ریاضی DAX، خواهد بود، نه لزوماً مقدار جایگزین پارامتر سوم. مقدار جایگزین تنها زمانی فعال میشود که مخرج صفر یا BLANK باشد.
Test Numerator Blank =
DIVIDE (
BLANK (),
100,
-1
)
در این مثال، چون مخرج صفر یا BLANK نیست، AlternateResult فعال نمیشود. صورت BLANK() است و نتیجه حاصل از این تقسیم نیز مطابق قواعد محاسباتی DAX با BLANK رفتار میکند. بنابراین نباید -1 را بهعنوان نتیجه این حالت در نظر گرفت.
مقایسه DIVIDE با IF برای مدیریت مخرج صفر
پیش از آشنایی با DIVIDE، بسیاری از توسعهدهندگان برای جلوگیری از نتیجه نامعتبر تقسیم بر صفر، از ترکیب IF و عملگر تقسیم استفاده میکردند.
با IF:
Budget Achievement Ratio =
IF (
[Total Budget] = 0 || ISBLANK ( [Total Budget] ),
BLANK (),
[Total Sales] / [Total Budget]
)
با DIVIDE:
Budget Achievement Ratio =
DIVIDE (
[Total Sales],
[Total Budget]
)
هر دو Measure از نظر منطقی همان نتیجه را تولید میکنند، اما نسخه DIVIDE بهطور محسوس خواناتر و کوتاهتر است. علاوه بر خوانایی، DIVIDE بهعنوان یک تابع اختصاصی برای این هدف طراحی شده و منطق بررسی مخرج صفر یا BLANK را در داخل خودش انجام میدهد، بدون آنکه توسعهدهنده مجبور باشد این شرط را بهصورت دستی و در هر Measure جداگانه بازنویسی کند. این یکدستی در سطح مدل، احتمال فراموش کردن بررسی مخرج صفر در برخی Measureها را نیز کاهش میدهد.
تأثیر DIVIDE بر Performance
سؤالی که در پروژههای سازمانی با حجم بالای محاسبات تقسیمی مطرح میشود این است که آیا استفاده از DIVIDE هزینه اضافهای نسبت به عملگر تقسیم معمولی به مدل تحمیل میکند یا خیر.
از نظر Performance، DIVIDE برای بررسی مخرج نسبت به الگوی دستی مبتنی بر IF بهینهتر است. بنابراین وقتی مخرج یک Expression است که ممکن است مقدار صفر یا BLANK داشته باشد، استفاده از DIVIDE انتخاب پیشنهادی است. با این حال، این به معنی برتری مطلق DIVIDE در تمام شرایط نیست. اگر مخرج یک مقدار ثابت و غیرصفر باشد، استفاده از عملگر / توصیه میشود، زیرا در این حالت نیازی به بررسی مخرج وجود ندارد.
مخرج ثابت و غیرصفر، نیازی به DIVIDE نیست:
Half Value =
Sales[Amount] / 2
سناریوهایی که باید با دقت بیشتری بررسی شوند
در محاسباتی که DIVIDE در داخل یک Iterator با تعداد بسیار زیاد تکرار قرار میگیرد، مانند فراخوانی آن برای میلیونها ردیف در یک SUMX، هزینه تجمعی این بررسی شرطی، هرچند در هر تکرار ناچیز است، میتواند در مجموع قابل اندازهگیری شود.
Row Level Ratio =
SUMX (
Sales,
DIVIDE ( Sales[Profit], Sales[Amount] )
)
در چنین سناریوهایی، مسئله اصلی معمولاً خود DIVIDE نیست، بلکه ضرورت واقعی محاسبه در سطح هر ردیف است. پیش از بررسی هزینه DIVIDE، ابتدا باید مشخص شود که آیا واقعاً نیاز به تقسیم در سطح هر ردیف وجود دارد یا میتوان صورت و مخرج را ابتدا در سطح مناسب تجمیع کرد و سپس یکبار تقسیم را در سطح Aggregate انجام داد. در عمل، هزینه اصلی معمولاً از خود ساختار Iterator ناشی میشود، نه از DIVIDE بهتنهایی، و رفتار واقعی باید با DAX Studio روی داده واقعی سازمان اندازهگیری شود.
DIVIDE در محاسبات مالی و درصدی حساس
در گزارشهای مالی سازمانی که دقت اعداد اهمیت بالایی دارد، ترکیب DIVIDE با ROUND برای کنترل دقت عددی نتیجه، الگویی رایج است.
Profit Margin Percentage =
ROUND (
DIVIDE (
[Total Profit],
[Total Sales]
),
4
)
در این Measure، ابتدا DIVIDE بهصورت امن نسبت سود به فروش را محاسبه میکند و سپس ROUND دقت نتیجه را به چهار رقم اعشار محدود میکند. این ترکیب بهخصوص در KPIهایی که قرار است در تصمیمات مدیریتی حساس، مانند تخصیص پاداش یا ارزیابی عملکرد، استفاده شوند، اهمیت زیادی دارد. اگر هدف تنها تغییر نحوه نمایش مقدار باشد، نه تغییر خود عدد ذخیرهشده، بهتر است بهجای تبدیل Measure به متن با FORMAT، از تنظیمات Formatting خود Power BI استفاده شود، زیرا FORMAT خروجی را به نوع متنی تبدیل میکند و اگر همان Measure قرار باشد در محاسبات دیگری نیز استفاده شود، این تبدیل میتواند مشکلساز شود.
خروجی یک Measure نسبتی مانند Profit Margin Percentage بهصورت یک عدد اعشاری تولید میشود؛ برای مثال مقدار ۰.۲۵ معادل بیستوپنج درصد است. اگر هدف نمایش مقدار به شکل درصد باشد، بهتر است Data Format همان Measure در Power BI روی Percentage تنظیم شود و نیازی به ضرب نتیجه در عدد صد در سطح فرمول وجود ندارد.
استفاده از DIVIDE در سطحبندی و شاخصهای شرطی
یکی دیگر از کاربردهای رایج DIVIDE، ترکیب آن با IF برای ساخت شاخصهای سطحبندیشده بر اساس نسبتهای محاسبهشده.
Margin Health Indicator =
VAR MarginRatio =
DIVIDE ( [Total Profit], [Total Sales] )
RETURN
IF (
ISBLANK ( MarginRatio ),
"بدون داده",
IF (
MarginRatio >= 0.3,
"سالم",
IF (
MarginRatio >= 0.1,
"قابل بررسی",
"بحرانی"
)
)
)
استفاده از VAR باعث میشود Expression مربوط به نسبت یکبار در ساختار Measure تعریف شود و همان نتیجه در شرطهای بعدی استفاده شود. علاوه بر خوانایی بهتر، این الگو از تکرار Expression در متن Measure جلوگیری میکند.
اشتباهات رایج در استفاده از DIVIDE
استفاده از عملگر تقسیم معمولی در Measureهای عمومی
رایجترین اشتباه، استفاده مستقیم از عملگر اسلش برای هر نوع تقسیم در سطح Measure است، بدون در نظر گرفتن این احتمال که مخرج در برخی سطرهای گزارش میتواند صفر یا BLANK شود. این اشتباه معمولاً در فاز توسعه با داده تستی کامل خودش را نشان نمیدهد و تنها در محیط عملیاتی، با داده واقعی و ناقص، بهصورت یک مقدار نامعتبر مانند Infinity در Visual ظاهر میشود.
فراموش کردن انتخاب آگاهانه پارامتر سوم
بسیاری از توسعهدهندگان همیشه از DIVIDE بدون پارامتر سوم استفاده میکنند و مقدار پیشفرض BLANK را بدون بررسی نیاز واقعی گزارش میپذیرند. در بسیاری از داشبوردهای مدیریتی، نمایش صفر بهجای خالی بودن سلول، خوانایی و قابلیت مقایسه گزارش را بهبود میدهد و باید آگاهانه انتخاب شود.
تبدیل ناخواسته BLANK به صفر
در طراحی Measureهای Power BI، استفاده از BLANK همیشه به معنی «مشکل» نیست. در بسیاری از سناریوها، BLANK دقیقاً بیانگر این است که مقدار قابل محاسبهای وجود ندارد. به همین دلیل، توصیه میشود تا حد امکان BLANK در Measureها حفظ شود و فقط زمانی به صفر تبدیل شود که صفر واقعاً همان معنای تحلیلی موردنظر را داشته باشد؛ تبدیل بیرویه BLANK به صفر میتواند باعث شود Visualها گروههای بدون داده را نیز نمایش دهند و خوانایی و حتی Performance گزارش را کاهش دهد.
استفاده از DIVIDE برای پوشاندن خطاهای منطقی مدل
گاهی DIVIDE بهاشتباه بهعنوان راهی برای پنهان کردن یک مشکل واقعی در مدل داده استفاده میشود، مانند رابطه نادرست بین جداول که باعث میشود مخرج همیشه صفر باشد. در چنین شرایطی، DIVIDE فقط نتیجه نامطلوب اجرایی را از بین میبرد، اما مشکل ریشهای مدل همچنان باقی میماند و باید بهطور جداگانه بررسی و اصلاح شود.
نادیده گرفتن تفاوت BLANK و صفر در تفسیر گزارش
انتخاب نادرست بین BLANK و صفر بهعنوان مقدار جایگزین میتواند تفسیر گزارش را برای کاربر نهایی گمراهکننده کند؛ برای مثال نمایش صفر درصد برای محصولی که اصلاً هنوز به بازار عرضه نشده، ممکن است بهاشتباه بهعنوان عملکرد ضعیف تفسیر شود، در حالی که BLANK بهدرستی نشان میدهد دادهای برای مقایسه وجود ندارد.
Best Practiceهای استفاده از DIVIDE در پروژههای سازمانی
در Measureهایی که مخرج آنها یک Expression پویا است و میتواند در برخی سطرهای Filter Context صفر یا BLANK شود، باید بهجای عملگر اسلش معمولی از DIVIDE استفاده شود. اگر مخرج یک مقدار ثابت و همیشه غیرصفر باشد، عملگر تقسیم معمولی گزینه سادهتر و کافی است.
انتخاب مقدار پارامتر سوم باید بر اساس معنای واقعی گزارش و نحوه نمایش آن در Visual انجام شود، نه صرفاً با پذیرفتن مقدار پیشفرض BLANK بدون بررسی، و باید در نظر داشت که این مقدار حتماً باید یک عدد یا متن ثابت باشد، نه یک Expression محاسباتی.
در این Measure، نتیجه نسبت سود به فروش تا چهار رقم اعشار گرد میشود. اگر هدف فقط کنترل نحوه نمایش عدد باشد و نیازی به تغییر مقدار محاسباتی وجود نداشته باشد، بهتر است از تنظیمات Formatting خود Power BI استفاده شود.
در Measureهای پیچیده که نتیجه DIVIDE چندین بار در شرطهای مختلف استفاده میشود، محاسبه آن در یک VAR و استفاده مجدد از همان متغیر، هم خوانایی کد و هم Performance را بهبود میدهد.
اگر مخرج یک محاسبه همیشه یا اغلب صفر است، پیش از تکیه صرف بر DIVIDE برای پوشاندن این وضعیت، باید ریشه مشکل در مدل داده یا منطق محاسبه بررسی شود.
جمعبندی
DIVIDE یکی از توابع مهم DAX برای محاسبات نسبتی و تقسیمهای ایمن است که با جایگزین کردن یک بررسی شرطی داخلی بهجای نیاز به نوشتن دستی IF و ISBLANK در هر Measure، هم خوانایی کد را افزایش میدهد و هم احتمال بروز نتایج نامطلوب مانند Infinity یا NaN را در محیط عملیاتی بهطور محسوس کاهش میدهد.
استفاده صحیح از DIVIDE فراتر از صرفاً جایگزینی عملگر اسلش است؛ انتخاب آگاهانه پارامتر سوم ثابت بر اساس معنای واقعی گزارش، حفظ BLANK در جایی که واقعاً به معنای نبود داده است، ترکیب آن با ROUND در محاسبات مالی حساس و استفاده از VAR برای جلوگیری از محاسبه تکراری، همگی بخشی از تسلط کامل بر این تابع در پروژههای سازمانی Power BI محسوب میشوند. در نهایت، باید توجه داشت که DIVIDE ابزاری برای مدیریت ایمن محاسبات تقسیمی است، نه راهکاری برای پنهان کردن مشکلات ریشهای در طراحی مدل داده.
سوالات متداول FAQ
چرا استفاده از عملگر تقسیم معمولی در DAX میتواند مشکلساز باشد؟
زیرا اگر مخرج در هر یک از سطرهای Filter Context صفر باشد، عملگر تقسیم معمولی میتواند مقادیری مانند Infinity یا NaN تولید کند که برای نمایش در گزارش مناسب نیستند. DIVIDE این حالت را بهصورت کنترلشده مدیریت میکند.
مقدار پیشفرض DIVIDE در صورت صفر بودن مخرج چیست؟
اگر پارامتر سوم مشخص نشود، مقدار پیشفرض BLANK است. با تعیین صریح پارامتر سوم، که باید یک مقدار ثابت باشد، میتوان هر مقدار دیگری مانند صفر یا یک عدد نشانگر را جایگزین کرد.
آیا DIVIDE به مقدار صورت کسر هم واکنش نشان میدهد؟
خیر. رفتار خاص DIVIDE فقط بر اساس مقدار مخرج تعیین میشود. اگر مخرج مقدار معتبری داشته باشد، حتی اگر صورت BLANK باشد، DIVIDE مانند یک تقسیم معمولی رفتار میکند و پارامتر سوم فعال نمیشود.
آیا استفاده از DIVIDE Performance مدل را کاهش میدهد؟
برای مخرجی که ممکن است صفر یا BLANK شود، DIVIDE نسبت به الگوی دستی مبتنی بر IF بهینهتر است. اما اگر مخرج یک مقدار ثابت و همیشه غیرصفر باشد، استفاده از عملگر تقسیم معمولی کافی و سادهتر است. در محاسبات سطر به سطر بسیار پرتکرار روی جداول بزرگ، بررسی ضرورت واقعی تقسیم در سطح هر ردیف مهمتر از نگرانی درباره هزینه DIVIDE بهتنهایی است.
پیشنهاد مطالعه
- مرجع زبان DAX افزونه کوئری نویسی در اکسل و POWER BI
- مرجع زبان فرمول نویسی M در پاور کوئری
- طراحی داشبوردهای مدیریتی در Microsoft Power BI
چه زمانی باید صفر را بهجای BLANK بهعنوان مقدار جایگزین انتخاب کرد؟
زمانی که عدم وجود داده باید از نظر تحلیلی به معنای «تحقق صفر درصد» یا یک مقدار عددی معنادار تفسیر شود، نه نبود کامل داده. اگر هدف نشان دادن این باشد که اصلاً دادهای برای مقایسه وجود ندارد، حفظ BLANK انتخاب مناسبتری است.
طراحی صحیح محاسبات تقسیمی در DAX، همراه با انتخاب آگاهانه رفتار Measure در برابر دادههای ناقص یا صفر، تأثیر مستقیمی بر دقت و پایداری گزارشهای مدیریتی در Power BI دارد. تیم توسعه فناوری اطلاعات لاندا با تمرکز بر مشاوره تخصصی Power BI، طراحی Measureهای دقیق و بهینهسازی DAX، آماده همراهی سازمانها در ساخت گزارشهای تحلیلی قابل اعتماد است.


No comment