COUNT, COUNTX, COUNTA, COUNTAX, COUNTROWS, DAX, DAX Functions, Power BI, AdventureWorksDW, VertiPaq, Formula Engine, Storage Engine, Iterator Functions, Power BI Performance, DAX Performance, DAX Measure, تفاوت COUNT و COUNTX, تفاوت COUNTA و COUNTAX, COUNTROWS در DAX, توابع شمارش DAX, توابع DAX, آموزش DAX, آموزش Power BI, شمارش در DAX, توابع Iterator در DAX, بهینه سازی DAX, بهینه سازی Power BI, Performance در Power BI, مدل داده Power BI, Measure در Power BI, AdventureWorksDW Power BI, COUNTAX در DAX, COUNTX در DAX, COUNTA در DAX, COUNT در DAX

در میان توابع شمارش DAX، شاید هیچ گروهی به‌اندازه COUNT، COUNTX، COUNTA و COUNTAX دچار خلط مبحث در تیم‌های توسعه Power BI نشده باشد. در نگاه اول، هر چهار تابع کاری شبیه به هم انجام می‌دهند: شمارش تعداد مقادیر. اما تفاوت‌های ظریف این توابع در نحوه برخورد با مقادیر Null، انواع داده‌ای قابل شمارش و معماری اجرایی آن‌ها، می‌تواند نتایج کاملاً متفاوتی تولید کند، حتی زمانی که روی یک ستون یکسان اجرا شوند.

این موضوع در پروژه‌های سازمانی اهمیت زیادی دارد، زیرا انتخاب نادرست تابع شمارش می‌تواند باعث شود یک KPI مدیریتی، مانند تعداد مشتریان فعال یا تعداد تراکنش‌های ثبت‌شده، عددی نادرست گزارش دهد بدون آنکه هیچ خطای اجرایی رخ دهد. در این مقاله با استفاده از جداول استاندارد مدل نمونه AdventureWorksDW، شامل FactInternetSales، DimCustomer و DimProduct، تفاوت دقیق این چهار تابع را از منظر یک کارشناس ارشد DAX بررسی می‌کنیم.

تعریف COUNT و محدودیت نوع داده آن

COUNT تعداد مقادیر غیرخالی یک ستون را می‌شمارد، اما فقط زمانی که ستون از نوع عددی باشد. از آنجا که مقادیر تاریخ و زمان نیز در موتور Tabular به‌صورت عدد ذخیره می‌شوند، این تابع روی آن‌ها نیز قابل استفاده است. اگر ستون از نوع متنی باشد، COUNT قابل استفاده نیست و باید از COUNTA استفاده شود.

Internet Sales Count =
COUNT ( FactInternetSales[SalesOrderNumber] )

نکته‌ای که در بسیاری از تیم‌های توسعه اشتباه فهمیده می‌شود این است که ستون SalesOrderNumber در FactInternetSales در واقع از نوع متنی است، نه عددی. به همین دلیل نوشتن Measure بالا با خطا مواجه می‌شود، زیرا COUNT قادر به پردازش مستقیم ستون‌های متنی نیست.

مثال درست COUNT روی یک ستون عددی واقعی:

Order Quantity Count =
COUNT ( FactInternetSales[OrderQuantity] )

این Measure تعداد ردیف‌هایی از FactInternetSales را برمی‌گرداند که مقدار OrderQuantity در آن‌ها Null نیست. از آنجا که تقریباً در تمام رکوردهای فروش این ستون مقدار دارد، نتیجه معمولاً برابر با تعداد کل ردیف‌های Filter Context فعلی خواهد بود.

مثال دیگر با ستونی که مقدار Null دارد، مانند PromotionKey در برخی مدل‌ها که ممکن است در سناریوهای خاص خالی باشد:

Promotion Count =
COUNT ( FactInternetSales[PromotionKey] )

اگر بخشی از تراکنش‌ها فاقد کد تخفیف باشند و مقدار PromotionKey برای آن‌ها Null یا Blank ذخیره شده باشد، COUNT فقط رکوردهایی را می‌شمارد که این ستون مقدار داشته باشد، نه کل ردیف‌های جدول.

چرا COUNT محدود به انواع خاص است

COUNT به گونه‌ای طراحی شده است که فقط روی ستون‌های عددی عمل کند. از آنجا که موتور VertiPaq مقادیر عددی را به‌صورت ستونی و فشرده نگهداری می‌کند، این تابع معمولاً می‌تواند شمارش را با کمترین سربار انجام دهد. البته سرعت اجرای واقعی همچنان به ساختار مدل، Filter Context و برنامه اجرایی موتور بستگی دارد.

تعریف COUNTA و پشتیبانی از هر نوع داده

COUNTA نیز مانند COUNT تعداد سلول‌های غیرخالی یک ستون را می‌شمارد، اما بر خلاف COUNT، هیچ محدودیتی در نوع داده ندارد و می‌تواند روی ستون‌های متنی، عددی، تاریخ و منطقی به‌یک‌اندازه اجرا شود.

Sales Order Number Count =
COUNTA ( FactInternetSales[SalesOrderNumber] )

از آنجا که SalesOrderNumber یک ستون متنی است، این Measure دقیقاً همان کاری را انجام می‌دهد که تلاش برای اجرای COUNT روی همین ستون با خطا مواجه می‌شد. COUNTA تعداد رکوردهایی را برمی‌گرداند که مقدار SalesOrderNumber در آن‌ها خالی نیست.

مثال دیگر روی ستون EmailAddress در DimCustomer:

Customers With Email =
COUNTA ( DimCustomer[EmailAddress] )

این Measure تعداد مشتریانی را می‌شمارد که مقدار EmailAddress برایشان ثبت شده است. اگر بخشی از مشتریان به هر دلیلی ایمیل ثبت‌شده نداشته باشند، این رکوردها در شمارش لحاظ نمی‌شوند.

تفاوت رفتار COUNT و COUNTA در برابر رشته خالی

نکته ظریفی که باید در نظر گرفت این است که یک رشته خالی از نوع متنی، یعنی مقداری که در ظاهر چیزی نمایش نمی‌دهد اما از نظر فنی Null نیست، توسط COUNTA به‌عنوان مقدار معتبر شمرده می‌شود، در حالی که مقدار واقعی Blank یا Null در هر دو تابع نادیده گرفته می‌شود. این تفاوت به‌خصوص در ستون‌هایی مانند AddressLine2 در DimCustomer اهمیت دارد، جایی که تفکیک بین یک آدرس واقعاً خالی و یک رشته خالی وارد‌شده از سیستم منبع می‌تواند نتیجه شمارش را تغییر دهد.

تعریف COUNTX و منطق Iterator در شمارش

COUNTX ابتدا Expression را برای هر ردیف جدول ارزیابی می‌کند. اگر نتیجه این ارزیابی یک مقدار عددی غیر Blank باشد، آن ردیف در شمارش لحاظ می‌شود. بنابراین ملاک شمارش، نتیجه نهایی Expression است، نه مقدار اولیه ستون.

Total Line Items =
COUNTX ( FactInternetSales, FactInternetSales[OrderQuantity] )

در این مثال ساده، نتیجه با COUNT روی همان ستون یکسان خواهد بود، زیرا Expression صرفاً همان ستون است. اما قدرت واقعی COUNTX زمانی نمایان می‌شود که Expression شامل یک محاسبه واقعی باشد.

Profitable Lines Count =
COUNTX (
    FactInternetSales,
    FactInternetSales[SalesAmount] - FactInternetSales[TotalProductCost]
)

این Measure برای هر ردیف از FactInternetSales، اختلاف SalesAmount و TotalProductCost را محاسبه می‌کند و اگر نتیجه یک عدد معتبر باشد، آن ردیف را می‌شمارد. از آنجا که این Expression تقریباً همیشه یک مقدار عددی معتبر تولید می‌کند، در این حالت خاص، نتیجه معادل شمارش کل ردیف‌های جدول خواهد بود. اما اگر Expression شامل یک عملیات تقسیم باشد که در برخی ردیف‌ها ممکن است خطای تقسیم بر صفر یا مقدار نامعتبر تولید کند، رفتار COUNTX متفاوت خواهد شد.

Valid Margin Ratio Count =
COUNTX (
    FactInternetSales,
    DIVIDE (
        FactInternetSales[SalesAmount] - FactInternetSales[TotalProductCost],
        FactInternetSales[SalesAmount]
    )
)

با استفاده از DIVIDE که در صورت تقسیم بر صفر مقدار Blank برمی‌گرداند، COUNTX فقط ردیف‌هایی را می‌شمارد که این نسبت واقعاً قابل محاسبه بوده است. این تفاوت دقیقاً نشان می‌دهد که COUNTX نه یک ستون، بلکه نتیجه یک محاسبه پویا را می‌شمارد.

در این مثال از تابع DIVIDE به‌جای عملگر / استفاده شده است، زیرا DIVIDE در صورت صفر بودن یا خالی بودن مخرج، به‌جای ایجاد خطا مقدار Blank برمی‌گرداند. از آنجا که COUNTX فقط نتایج عددی غیر Blank را می‌شمارد، ردیف‌هایی که نسبت سود آن‌ها قابل محاسبه نباشد، به‌طور خودکار از شمارش حذف می‌شوند.

آرگومان سوم DIVIDE
DIVIDE ( Numerator, Denominator, AlternateResult )

آرگومان سوم DIVIDE اختیاری است و مشخص می‌کند اگر مخرج صفر یا Blank باشد، چه مقداری برگردانده شود. اگر این آرگومان نوشته نشود، خروجی تابع Blank خواهد بود. اما در صورت نیاز می‌توان مقدار جایگزینی مانند صفر یا هر مقدار ثابت دیگری را تعیین کرد.

مثال:

Margin Ratio =
DIVIDE (
    FactInternetSales[SalesAmount] - FactInternetSales[TotalProductCost],
    FactInternetSales[SalesAmount],
    0
)

در این مثال، اگر مقدار SalesAmount صفر یا Blank باشد، تابع به‌جای Blank مقدار 0 را برمی‌گرداند.

انتخاب آرگومان سوم DIVIDE می‌تواند نتیجه COUNTX را نیز تغییر دهد. اگر آرگومان سوم نوشته نشود، ردیف‌هایی که تقسیم در آن‌ها قابل انجام نیست مقدار Blank تولید می‌کنند و توسط COUNTX شمارش نمی‌شوند. اما اگر مقدار جایگزینی مانند 0 تعیین شود، خروجی دیگر Blank نخواهد بود و همان ردیف‌ها نیز در شمارش لحاظ می‌شوند. به همین دلیل، انتخاب مقدار جایگزین در DIVIDE باید با منطق کسب‌وکار و هدف Measure هماهنگ باشد.

مسیر اجرای داخلی COUNTX

FactInternetSales
        │
        ▼
پیمایش ردیف به ردیف
        │
        ▼
ایجاد Row Context برای هر ردیف
        │
        ▼
ارزیابی Expression در همان ردیف
        │
        ▼
بررسی معتبر بودن نتیجه عددی
        │
        ▼
جمع تعداد ردیف‌های دارای نتیجه معتبر

این مسیر دقیقاً همان الگوی اجرایی است که در سایر X Functionها مانند SUMX دیده می‌شود، با این تفاوت که به‌جای جمع مقادیر، تعداد نتایج معتبر شمارش می‌شود.

تعریف COUNTAX و شمارش مبتنی بر Expression با هر نوع داده

COUNTAX ترکیبی از منطق COUNTA و COUNTX است. این تابع نیز مانند COUNTX یک جدول و یک Expression می‌گیرد و برای هر ردیف آن را ارزیابی می‌کند، اما برخلاف COUNTX که فقط نتایج عددی معتبر را می‌شمارد، COUNTAX هر مقداری به‌جز Blank را می‌شمارد، از جمله مقادیر متنی.

Product Color Description Count =
COUNTAX (
    DimProduct,
    DimProduct[Color]
)

این Measure برای هر محصول در DimProduct، مقدار ستون Color را ارزیابی می‌کند و تعداد محصولاتی را می‌شمارد که این مقدار خالی نیست. از آنجا که Color یک ستون متنی است، اگر بخواهیم همین منطق را با COUNTX پیاده‌سازی کنیم، با خطا مواجه می‌شویم، زیرا COUNTX تنها نتایج عددی را می‌پذیرد.

مثال دیگر با یک Expression ترکیبی متنی:

Full Product Description Count =
COUNTAX (
    DimProduct,
    DimProduct[EnglishProductName] & " - " & DimProduct[Color]
)

در این مثال، برای هر محصول یک رشته ترکیبی از نام و رنگ ساخته می‌شود. از آنجا که این ترکیب همیشه یک مقدار متنی معتبر تولید می‌کند، حتی اگر Color خالی باشد و ترکیب رشته با یک مقدار خالی همراه شود، COUNTAX همچنان آن را به‌عنوان یک نتیجه غیرخالی می‌شمارد. این نکته باید در طراحی چنین Expressionهایی مورد توجه قرار گیرد، زیرا رفتار Concatenation در برابر Null با رفتار عملیات ریاضی متفاوت است.

جدول مقایسه‌ای چهار تابع

برای درک بهتر تفاوت این چهار تابع، جدول زیر رفتار آن‌ها را در برابر سه معیار اصلی مقایسه می‌کند.

تابع ورودی انواع داده قابل شمارش نادیده گرفتن Null
COUNT یک ستون فقط عددی، تاریخ و مشابه بله
COUNTA یک ستون تمام انواع داده بله
COUNTX جدول و Expression فقط نتایج عددی معتبر بله
COUNTAX جدول و Expression تمام انواع نتایج بله

این جدول نشان می‌دهد که تمایز اصلی در دو محور مستقل قرار دارد: محور اول اینکه ورودی تابع یک ستون ساده است یا یک Expression قابل محاسبه در سطح هر ردیف، و محور دوم اینکه تابع محدود به مقادیر عددی است یا هر نوع داده را می‌پذیرد.

تفاوت COUNT و COUNTROWS

یکی از رایج‌ترین پرسش‌هایی که هنگام یادگیری توابع شمارش DAX مطرح می‌شود، تفاوت COUNT و COUNTROWS است. هرچند هر دو در بسیاری از گزارش‌ها برای شمارش استفاده می‌شوند، اما هدف طراحی آن‌ها کاملاً متفاوت است.

COUNT تعداد مقادیر غیر Blank یک ستون عددی را می‌شمارد. بنابراین نتیجه آن به مقدارهای موجود در همان ستون وابسته است. اگر برخی ردیف‌های ستون مقدار نداشته باشند، آن ردیف‌ها در شمارش لحاظ نمی‌شوند.

Order Quantity Count =
COUNT ( FactInternetSales[OrderQuantity] )

در مقابل، COUNTROWS هیچ ستونی را بررسی نمی‌کند، بلکه تعداد ردیف‌های یک جدول یا یک عبارت جدولی را برمی‌گرداند. در نتیجه وجود یا نبود مقدار در یک ستون خاص تأثیری بر خروجی آن ندارد.

Internet Sales Rows =
COUNTROWS ( FactInternetSales )

اگر جدول FactInternetSales شامل ۶۰ هزار رکورد باشد، COUNTROWS مقدار ۶۰ هزار را برمی‌گرداند، حتی اگر برخی ستون‌های جدول دارای مقدار Blank باشند.

تفاوت زمانی آشکارتر می‌شود که ستونی دارای مقادیر خالی باشد.

Promotion Count =
COUNT ( FactInternetSales[PromotionKey] )

Sales Rows =
COUNTROWS ( FactInternetSales )

در این مثال، اگر بخشی از سفارش‌ها فاقد PromotionKey باشند، COUNT فقط ردیف‌هایی را می‌شمارد که مقدار PromotionKey دارند، اما COUNTROWS تمام ردیف‌های جدول را بدون توجه به مقدار این ستون محاسبه می‌کند.

تفاوت مهم دیگر این است که COUNTROWS می‌تواند روی هر عبارت جدولی نیز اجرا شود، نه فقط روی یک جدول فیزیکی.

High Value Orders =
COUNTROWS (
    FILTER (
        FactInternetSales,
        FactInternetSales[SalesAmount] > 1000
    )
)

در این Measure ابتدا تابع FILTER فقط سفارش‌هایی را نگه می‌دارد که مبلغ فروش آن‌ها بیش از ۱۰۰۰ است و سپس COUNTROWS تعداد همین ردیف‌ها را برمی‌گرداند. به همین دلیل، COUNTROWS در بسیاری از محاسبات شرطی یکی از پرکاربردترین توابع شمارش در DAX محسوب می‌شود.

در بسیاری از سناریوهای واقعی، اگر هدف شمارش تعداد ردیف‌های یک جدول یا نتیجه یک عبارت جدولی باشد، COUNTROWS انتخاب مناسب‌تری نسبت به COUNT است. در مقابل، زمانی که هدف شمارش تعداد مقادیر موجود در یک ستون مشخص باشد، به‌ویژه اگر وجود یا نبود مقدار در آن ستون اهمیت داشته باشد، استفاده از COUNT انتخاب صحیح‌تری خواهد بود.

مقایسه COUNT و COUNTROWS

تابع ورودی چه چیزی را می‌شمارد وابسته به مقدار ستون
COUNT یک ستون عددی تعداد مقادیر غیر Blank بله
COUNTROWS جدول یا عبارت جدولی تعداد ردیف‌ها خیر

مثال ترکیبی روی مدل AdventureWorksDW برای مقایسه هر چهار تابع

برای نمایش دقیق تفاوت این توابع در یک سناریوی واحد، فرض کنید می‌خواهیم بررسی کنیم چند سفارش در FactInternetSales دارای یادداشت یا کد ارجاع خاص هستند، در ستونی فرضی به نام CarrierTrackingNumber که در برخی رکوردها Null است.

Count Numeric =
COUNT ( FactInternetSales[OrderQuantity] )

Count Any Type =
COUNTA ( FactInternetSales[CarrierTrackingNumber] )

Count By Expression Numeric =
COUNTX (
    FactInternetSales,
    FactInternetSales[OrderQuantity] * 1
)

Count By Expression Any Type =
COUNTAX (
    FactInternetSales,
    FactInternetSales[CarrierTrackingNumber]
)

در این مجموعه Measure، Count Numeric و Count By Expression Numeric از نظر نتیجه یکسان هستند، زیرا هر دو در نهایت مقدار عددی OrderQuantity را ارزیابی می‌کنند. به همین ترتیب، Count Any Type و Count By Expression Any Type نیز نتیجه یکسانی تولید می‌کنند، زیرا هر دو ستون متنی CarrierTrackingNumber را بدون محدودیت نوع داده می‌شمارند. تفاوت اصلی بین این دو جفت، وجود یا نبود Expression محاسباتی است، نه صرفاً نوع داده.

چه زمانی باید از هر یک استفاده کرد

انتخاب صحیح بین این چهار تابع باید بر اساس دو پرسش انجام شود: آیا نیاز به شمارش یک ستون ساده داریم یا نتیجه یک محاسبه، و آیا مقدار موردنظر عددی است یا می‌تواند هر نوع داده‌ای باشد.

وقتی هدف شمارش تعداد رکوردهای دارای مقدار در یک ستون عددی یا تاریخ است، بدون نیاز به هیچ محاسبه اضافه، COUNT گزینه بهینه است، زیرا سریع‌ترین مسیر اجرایی را دارد.

Orders With Quantity =
COUNT ( FactInternetSales[OrderQuantity] )

اگر همان هدف روی ستونی متنی مانند SalesOrderNumber یا EmailAddress موردنیاز است، COUNTA باید استفاده شود.

Customers With Phone =
COUNTA ( DimCustomer[Phone] )

زمانی که نیاز به شمارش نتیجه یک محاسبه عددی در سطح هر ردیف است، مانند شمارش تراکنش‌هایی که حاشیه سود مثبت دارند، COUNTX تنها گزینه مناسب است.

Positive Margin Count =
COUNTX (
    FactInternetSales,
    IF (
        FactInternetSales[SalesAmount] > FactInternetSales[TotalProductCost],
        1
    )
)

در این مثال، تابع IF برای ردیف‌هایی که شرط برقرار نیست، مقدار Blank تولید می‌کند و COUNTX تنها ردیف‌هایی را می‌شمارد که نتیجه IF برابر با یک بوده است. این الگو یکی از رایج‌ترین روش‌های شمارش شرطی مبتنی بر منطق محاسباتی در DAX است.

این مثال صرفاً برای نمایش رفتار COUNTX نوشته شده است. در برخی سناریوها، استفاده از FILTER به همراه COUNTROWS نیز می‌تواند گزینه مناسبی باشد و انتخاب بین این دو باید بر اساس خوانایی و بررسی Performance انجام شود.

اگر نتیجه محاسبه در سطح هر ردیف می‌تواند متنی یا از نوع دیگری غیر از عدد باشد، COUNTAX باید استفاده شود.

Named Category Count =
COUNTAX (
    DimProduct,
    DimProduct[EnglishProductSubcategoryName]
)

اشتباه رایج: استفاده از COUNTX در جایی که COUNT کافی است

مشابه الگویی که در مقایسه SUM و SUMX دیده می‌شود، یکی از رایج‌ترین اشتباهات، استفاده از COUNTX روی یک ستون ساده بدون هیچ Expression واقعی است.

غیربهینه:
Order Count =
COUNTX ( FactInternetSales, FactInternetSales[OrderQuantity] )

بهینه:
Order Count =
COUNT ( FactInternetSales[OrderQuantity] )

در این مثال، استفاده از COUNTX باعث می‌شود موتور برای هر ردیف Expression را ارزیابی کند، در حالی که COUNT می‌تواند مستقیماً روی ستون عمل کند. زمانی که هیچ محاسبه‌ای در سطح ردیف وجود ندارد، استفاده از COUNT معمولاً انتخاب مناسب‌تری است.

دیگر اشتباه رایج: تلاش برای استفاده از COUNT روی ستون متنی

خطای رایج دیگر، تلاش برای استفاده از COUNT روی ستون‌هایی مانند SalesOrderNumber یا EnglishProductName است که از نوع متنی هستند.

نامعتبر:
COUNT ( FactInternetSales[SalesOrderNumber] )

معتبر:
COUNTA ( FactInternetSales[SalesOrderNumber] )

این خطا معمولاً در همان مرحله نگارش Measure توسط Power BI شناسایی و گزارش می‌شود، اما در تیم‌های تازه‌کار می‌تواند باعث سردرگمی شود، به‌خصوص وقتی توسعه‌دهنده انتظار دارد COUNT روی هر نوع ستونی کار کند.

تأثیر این توابع بر Performance در مدل‌های حجیم

از منظر موتور DAX، COUNT و COUNTA به دلیل عملکرد مستقیم روی یک ستون، معمولاً به‌طور کامل به Storage Engine منتقل می‌شوند و از پردازش ستونی فشرده VertiPaq بهره می‌برند. این دو تابع تقریباً همیشه سریع‌ترین گزینه برای شمارش ساده هستند.

COUNTX و COUNTAX، به دلیل نیاز به ایجاد Row Context و ارزیابی Expression در Formula Engine، هزینه اجرایی بیشتری دارند، به‌خصوص اگر Expression داخل آن‌ها شامل عملیات پیچیده، فراخوانی Measure دیگر یا Context Transition باشد.

پرهزینه در حجم بالا:
Complex Count =
COUNTX (
    FactInternetSales,
    CALCULATE ( [Total Sales] ) / FactInternetSales[OrderQuantity]
)

در چنین Expressionی، برای هر ردیف از FactInternetSales یک Context Transition کامل رخ می‌دهد و سپس یک عملیات تقسیم انجام می‌شود. در جدول‌هایی با حجم بالا، چنین ساختاری می‌تواند به‌طور محسوس Performance را کاهش دهد و پیش از استقرار نهایی باید با DAX Studio بررسی شود.

Best Practiceهای انتخاب تابع شمارش مناسب

پیش از نوشتن هر Measure شمارشی، باید مشخص شود که آیا شمارش روی یک ستون خام کافی است یا نیاز به یک Expression محاسباتی در سطح هر ردیف وجود دارد. اگر ستون خام کافی است، همیشه باید بین COUNT و COUNTA بر اساس نوع داده ستون انتخاب شود، نه بین COUNTX و COUNTAX.

اگر Expression واقعاً لازم است، باید بررسی شود که نتیجه آن عددی خواهد بود یا می‌تواند شامل مقادیر متنی نیز باشد، تا انتخاب درست بین COUNTX و COUNTAX انجام شود.

در Measureهای شمارش شرطی، استفاده از IF برای تولید مقدار Blank در ردیف‌های نامعتبر، همراه با COUNTX، یکی از تمیزترین الگوها برای شمارش شرطی در DAX است و نسبت به ترکیب FILTER با COUNTROWS در بسیاری از سناریوها خواناتر است.

نام‌گذاری Measureهای شمارشی باید به‌وضوح نوع شمارش را نشان دهد، مانند تفکیک بین شمارش رکوردهای دارای مقدار در یک ستون خاص در برابر شمارش کل ردیف‌های یک جدول، تا از تفسیر نادرست نتیجه توسط مصرف‌کنندگان گزارش جلوگیری شود.

پیش از استفاده گسترده از COUNTX یا COUNTAX روی جداول Fact بزرگ، Performance آن باید با DAX Studio روی داده واقعی سازمان اندازه‌گیری شود، به‌خصوص اگر Expression داخل آن‌ها شامل فراخوانی Measureهای دیگر باشد.

جمع‌بندی

COUNT، COUNTX، COUNTA و COUNTAX هرچند در نگاه اول شبیه به هم به نظر می‌رسند، از دو محور کاملاً مستقل با یکدیگر تفاوت دارند: نوع ورودی، که می‌تواند یک ستون ساده یا یک Expression محاسباتی باشد، و دامنه پذیرش نوع داده، که می‌تواند محدود به مقادیر عددی یا شامل هر نوع داده باشد. COUNT برای شمارش ساده ستون‌های عددی، COUNTA برای شمارش ساده هر نوع ستون، COUNTX برای شمارش نتایج عددی یک محاسبه سطر به سطر و COUNTAX برای شمارش هر نوع نتیجه یک محاسبه سطر به سطر طراحی شده‌اند.

انتخاب نادرست میان این چهار تابع، به‌خصوص استفاده غیرضروری از X Functionها در جایی که تابع ساده کافی است، می‌تواند هزینه اجرایی غیرضروری به مدل تحمیل کند. در مقابل، تلاش برای استفاده از توابع محدودتر مانند COUNT در جایی که نیاز واقعی به Expression یا داده متنی وجود دارد، منجر به خطا یا نتیجه نادرست می‌شود. تسلط بر این تفاوت‌های ظریف، بخشی جدایی‌ناپذیر از مهارت طراحی Measureهای دقیق و بهینه در پروژه‌های سازمانی Power BI است.

سوالات متداول FAQ

چرا COUNT روی ستون SalesOrderNumber در FactInternetSales خطا می‌دهد؟
زیرا COUNT فقط ستون‌های عددی، تاریخ یا انواع مشابه را می‌پذیرد و SalesOrderNumber از نوع متنی است. برای شمارش این ستون باید از COUNTA استفاده شود.

تفاوت اصلی COUNTX و COUNTAX چیست؟
هر دو یک جدول و یک Expression می‌گیرند و آن را در سطح هر ردیف ارزیابی می‌کنند، اما COUNTX تنها نتایجی را می‌شمارد که عددی معتبر باشند، در حالی که COUNTAX هر نوع نتیجه غیرخالی، از جمله متنی، را می‌شمارد.

آیا COUNTX همیشه کندتر از COUNT است؟
در شمارش ساده یک ستون بدون Expression واقعی، بله COUNTX هزینه اجرایی بیشتری دارد، زیرا نیازمند ایجاد Row Context برای هر ردیف است. اما در محاسبات شرطی یا مبتنی بر Expression، COUNTX تنها گزینه ممکن است.

چگونه می‌توان با COUNTX تعداد رکوردهای دارای یک شرط خاص را شمارد؟
با استفاده از IF داخل Expression که برای ردیف‌های واجد شرط مقدار عددی و برای سایر ردیف‌ها مقدار Blank تولید کند، سپس COUNTX تنها ردیف‌های دارای مقدار معتبر را می‌شمارد.

آیا COUNTA رشته خالی را با Null یکسان در نظر می‌گیرد؟
خیر. یک رشته خالی از نظر فنی مقدار معتبر محسوب می‌شود و توسط COUNTA شمارش می‌شود، در حالی که مقدار واقعی Null یا Blank نادیده گرفته می‌شود. این تفاوت باید در تحلیل داده‌های وارد‌شده از سیستم‌های منبع در نظر گرفته شود.

بهینه‌سازی Measureها و مدل‌های Power BI با لاندا

طراحی صحیح Measureهای DAX تنها به انتخاب تابع مناسب محدود نمی‌شود. در مدل‌های سازمانی، عواملی مانند ساختار مدل داده، روابط بین جداول، Filter Context، طراحی Measureها و نحوه اجرای محاسبات در موتور VertiPaq، همگی بر صحت KPIها و Performance گزارش‌ها تأثیر مستقیم دارند.

تیم توسعه فناوری اطلاعات لاندا با ارائه خدمات مشاوره تخصصی Power BI، طراحی و بازبینی Measureهای DAX، بهینه‌سازی مدل داده، تحلیل Performance با DAX Studio و بهبود سرعت گزارش‌های تحلیلی، به سازمان‌ها کمک می‌کند تا داشبوردهایی دقیق، سریع و مقیاس‌پذیر ایجاد کنند که پاسخگوی نیازهای تحلیلی در مقیاس Enterprise باشند.

برای دریافت مشاوره تخصصی، ارزیابی Performance یا برگزاری دوره‌های آموزشی عملی DAX، با کارشناسان لاندا تماس  بگیرید.

No comment

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *