Context Transition در DAX چیست؟
اگر در Power BI با DAX کار کرده باشید، احتمالاً به فرمولهایی رسیدهاید که در نگاه اول نتیجه آنها کمی عجیب به نظر میرسد. مخصوصاً زمانی که CALCULATE را داخل Calculated Column، Iteratorها یا توابعی مانند SUMX و FILTER استفاده میکنیم.
در این شرایط یک مفهوم بسیار مهم وارد ماجرا میشود:
Context Transition
شاید نام آن در ابتدا کمی تخصصی به نظر برسد، اما اگر مفهوم Row Context و Filter Context را بدانیم، فهم Context Transition بسیار سادهتر میشود.
به زبان ساده، Context Transition یعنی:
CALCULATE میتواند Row Context موجود را به Filter Context تبدیل کند.
البته این تعریف برای شروع مناسب است و جزئیات آن در سناریوهای مختلف DAX اهمیت پیدا میکند.
در این آموزش از مجموعه مقالات Power BI و DAX سایت آکادمی اشکاوند، ابتدا مفهوم Context Transition را با یک مثال ساده توضیح میدهیم، سپس سراغ CALCULATE، Calculated Column، Measure، SUMX و Relationship بین جداول میرویم تا ببینیم این مفهوم در پروژههای واقعی چه کاربردی دارد.
Contents
- 1. Context Transition چیست؟
- 2. یک مثال ساده برای درک بهتر Context Transition
- 3. CALCULATE و Context Transition
- 4. یک مثال واقعی؛ فروش هر مشتری
- 5. چرا بدون CALCULATE ممکن است نتیجه متفاوت باشد؟
- 6. Context Transition در Iteratorها
- 7. یک مثال کاربردی با SUMX
- 8. Context Transition در Calculated Column
- 9. نقش Relationship در Context Transition
- 10. Context Transition در FILTER
- 11. مثال واقعی؛ پیدا کردن مشتریان با فروش بالاتر از ۵۰ میلیون
- 12. Context Transition و Measure
- 13. آیا Context Transition همیشه اتفاق میافتد؟
- 14. یک مثال برای مقایسه
- 15. Context Transition را چگونه در ذهن خودمان نگه داریم؟
- 16. اشتباه رایج؛ حفظ کردن Context Transition بدون فهم Context
- 17. یک تمرین عملی برای یادگیری Context Transition
- 18. ارتباط Context Transition با مقالههای قبلی
- 19. جمعبندی
قبل از Context Transition؛ Row Context و Filter Context را بشناسیم
برای اینکه Context Transition را درست متوجه شویم، ابتدا باید تفاوت دو مفهوم را بدانیم.
Row Context یعنی DAX در حال ارزیابی یک ردیف مشخص است.
مثلاً اگر در یک Calculated Column بنویسیم:
Amount =
Sales[Quantity] * Sales[Unit Price]
فرمول برای هر ردیف بهصورت جداگانه ارزیابی میشود.
اما Filter Context مشخص میکند چه مجموعهای از دادهها در محاسبه حضور داشته باشند.
مثلاً اگر در یک Visual شهر تهران انتخاب شده باشد، Measure فروش میتواند فقط بر اساس دادههای تهران محاسبه شود.
پس به شکل ساده:
| مفهوم | معنی ساده |
|---|---|
| Row Context | الان روی کدام ردیف هستیم؟ |
| Filter Context | چه دادههایی در محاسبه قرار گرفتهاند؟ |
اگر هنوز این دو مفهوم برایتان کاملاً روشن نیست، بهتر است ابتدا مقاله Row Context و Filter Context در DAX را مطالعه کنید.
Context Transition چیست؟
حالا فرض کنید DAX در یک Row Context قرار دارد.
مثلاً در یک Calculated Column، Power BI در حال بررسی مشتری شماره 1005 است.
در حالت عادی این موضوع به معنی آن نیست که تمام محاسبات Measureها نیز فقط برای مشتری 1005 انجام شوند.
اینجاست که CALCULATE اهمیت پیدا میکند.
وقتی CALCULATE در یک Row Context اجرا شود، میتواند اطلاعات ردیف جاری را به فیلتر تبدیل کند.
یعنی بهصورت مفهومی:
Row Context => CALCULATE => Filter Context
این فرآیند همان Context Transition است.
یک مثال ساده برای درک بهتر Context Transition
فرض کنید جدول Customer داریم:
| CustomerID | CustomerName |
|---|---|
| 101 | علی رضایی |
| 102 | مریم احمدی |
| 103 | رضا کریمی |
و جدول Sales:
| CustomerID | Amount |
|---|---|
| 101 | 20M |
| 101 | 15M |
| 102 | 30M |
| 103 | 12M |
| 103 | 18M |
یک Measure داریم:
Total Sales =
SUM(Sales[Amount])
اگر این Measure را در یک Visual بر اساس CustomerName قرار دهیم، برای هر مشتری مقدار متفاوتی میبینیم.
مثلاً:
| مشتری | فروش |
|---|---|
| علی رضایی | 35M |
| مریم احمدی | 30M |
| رضا کریمی | 30M |
چرا؟
چون Visual برای هر مشتری یک Filter Context ایجاد میکند.
اما حالا یک سناریوی متفاوت را در نظر بگیرید.
میخواهیم در جدول Customer یک Calculated Column بسازیم که فروش هر مشتری را نشان دهد.
در نگاه اول شاید بنویسیم:
Customer Sales =
[Total Sales]
اما این فرمول الزاماً نتیجهای که انتظار داریم ایجاد نمیکند.
چرا؟
چون قرار گرفتن در یک Row Context بهتنهایی به این معنی نیست که همان CustomerID بهعنوان Filter Context روی جدول Sales اعمال شده است.
اینجاست که CALCULATE وارد میشود.
Customer Sales =
CALCULATE(
[Total Sales]
)
در این سناریو CALCULATE میتواند Row Context مربوط به مشتری جاری را به Filter Context تبدیل کند.
در نتیجه فروش مربوط به همان مشتری محاسبه میشود.
CALCULATE و Context Transition
یکی از مهمترین نکاتی که هنگام یادگیری DAX باید به خاطر بسپارید این است:
CALCULATE بدون آرگومان فیلتر هم میتواند مهم باشد.
ممکن است فکر کنید CALCULATE فقط زمانی کاربرد دارد که بعد از آن شرطی مانند:
Product[Category] = "Laptop"
بنویسیم.
اما اینطور نیست.
فرمول زیر را ببینید:
CALCULATE(
[Total Sales]
)
در صورتی که CALCULATE در یک Row Context اجرا شود، میتواند Context Transition ایجاد کند.
یعنی Row Context جاری به Filter Context تبدیل میشود.
این یکی از دلایلی است که CALCULATE را باید بسیار عمیقتر از یک «تابع فیلتر کردن» یاد گرفت.
یک مثال واقعی؛ فروش هر مشتری
فرض کنید جدول Customer داریم و میخواهیم برای هر مشتری مجموع خرید او را محاسبه کنیم.
Measure اصلی:
Total Sales =
SUM(Sales[Amount])
حالا در جدول Customer یک Calculated Column ایجاد میکنیم:
Customer Sales =
CALCULATE(
[Total Sales]
)
در اینجا CALCULATE اطلاعات مشتری جاری را از Row Context دریافت کرده و آن را به Filter Context تبدیل میکند.
سپس Measure [Total Sales] در این Context ارزیابی میشود.
به زبان ساده:
مشتری جاری =>Row Context =>CALCULATE => Filter Context مشتری => [Total Sales] =>فروش همان مشتری
این زنجیره را اگر بهخوبی متوجه شوید، بخش قابل توجهی از رفتار DAX برایتان قابل پیشبینی میشود.
چرا بدون CALCULATE ممکن است نتیجه متفاوت باشد؟
فرض کنید در Calculated Column جدول Customer بنویسیم:
Customer Sales =
[Total Sales]
در این حالت Measure اجرا میشود، اما Row Context جدول Customer الزاماً به فیلتر روی Sales تبدیل نشده است.
در نتیجه ممکن است مقدار Measure برای ردیفهای مختلف آن چیزی نباشد که انتظار دارید.
با اضافه کردن:
CALCULATE(
[Total Sales]
)
Context Transition اتفاق میافتد.
این همان تفاوت مهمی است که بسیاری از کاربران هنگام شروع DAX با آن مواجه میشوند.
Context Transition در Iteratorها
حالا به بخش جذابتر موضوع میرسیم.
توابع Iterator مانند:
SUMX
AVERAGEX
MINX
MAXX
FILTER
میتوانند هنگام پیمایش دادهها Row Context ایجاد کنند.
برای مثال:
SUMX(
Customer,
[Total Sales]
)
اینجا SUMX جدول Customer را ردیفبهردیف بررسی میکند.
اما سؤال مهم این است:
آیا [Total Sales] برای هر مشتری بهصورت جداگانه محاسبه میشود؟
اینجا Context Transition و نحوه ارزیابی Measure اهمیت پیدا میکند.
وقتی یک Measure در چنین سناریویی ارزیابی میشود، مکانیزمهای داخلی DAX و CALCULATE ضمنی موجود در ارزیابی Measure میتوانند باعث شوند Row Context روی محاسبه Measure اثر بگذارد.
به همین دلیل ترکیب Iterator و Measure از مباحث مهم DAX محسوب میشود.
یک مثال کاربردی با SUMX
فرض کنید میخواهیم فروش مشتریان را بررسی کنیم.
Customer Sales Total =
SUMX(
Customer,
[Total Sales]
)
در اینجا SUMX مشتریان را یکییکی پیمایش میکند و Measure فروش را برای Context مربوط به هر مشتری ارزیابی میکند.
اگر مدل داده و Relationshipها صحیح باشند، این الگو میتواند برای محاسبات تحلیلی بسیار کاربردی باشد.
البته برای محاسبه مجموع فروش کل، این فرمول لزوماً انتخاب مناسبی نیست و همان:
Total Sales =
SUM(Sales[Amount])
کافی است.
پس این مثال بیشتر برای درک Context است تا اینکه همیشه از آن برای محاسبه فروش کل استفاده کنیم.
Context Transition در Calculated Column
یکی از مکانهایی که این مفهوم را بهخوبی میتوان مشاهده کرد، Calculated Column است.
فرض کنید جدول Products داریم:
| ProductID | ProductName | Category |
|---|---|---|
| 1 | لپتاپ A | لپتاپ |
| 2 | مانیتور A | مانیتور |
| 3 | لپتاپ B | لپتاپ |
و جدول Sales از طریق ProductID به Products متصل است.
اگر بخواهیم فروش هر محصول را در جدول Products داشته باشیم:
Product Sales =
CALCULATE(
[Total Sales]
)
در هر ردیف Products یک Row Context وجود دارد.
CALCULATE میتواند این Context را به Filter Context تبدیل کند.
در نتیجه فیلتر محصول جاری روی جدول Sales اعمال میشود.
البته در مدلهای واقعی باید به Relationship بین Products و Sales نیز توجه داشته باشیم.
نقش Relationship در Context Transition
Context Transition بهتنهایی همه مشکلات مدل را حل نمیکند.
فرض کنید Relationship بین Products و Sales اشتباه باشد.
حتی اگر فرمول DAX کاملاً صحیح باشد، ممکن است فیلتر محصول به جدول Sales منتقل نشود یا نتیجه مورد انتظار ایجاد نشود.
پس وقتی یک Measure نتیجه اشتباه میدهد، همیشه نباید فوراً فرمول DAX را مقصر بدانیم.
این موارد را نیز بررسی کنید:
- Relationshipها
- جهت Filter
- نوع Relationship
- کلیدهای ارتباطی
- وجود دادههای تکراری
- جدول Date
- Context فعلی Visual
مدل داده مناسب، بخش مهمی از یک گزارش Power BI حرفهای است.
Context Transition در FILTER
در مقاله آموزش FILTER دیدیم که FILTER میتواند یک جدول را ردیفبهردیف بررسی کند.
مثلاً:
FILTER(
Customer,
[Total Sales] > 50000000
)
اینجا یک نکته مهم وجود دارد.
ما در حال پیمایش مشتریان هستیم و برای هر مشتری میخواهیم [Total Sales] را بررسی کنیم.
در چنین سناریوهایی درک Context بسیار مهم است.
به زبان ساده، برای اینکه DAX بتواند بفهمد:
«فروش همین مشتری چقدر است؟»
باید Context مربوط به مشتری جاری در محاسبه لحاظ شود.
این دقیقاً یکی از جاهایی است که شناخت Context Transition و رفتار Measureها به شما کمک میکند فرمولهای DAX را بهتر درک کنید.
مثال واقعی؛ پیدا کردن مشتریان با فروش بالاتر از ۵۰ میلیون
فرض کنید میخواهیم مشتریانی را پیدا کنیم که مجموع خریدشان بیشتر از ۵۰ میلیون تومان بوده است.
یک الگوی DAX میتواند به شکل زیر باشد:
High Value Customers =
FILTER(
VALUES(Customer[CustomerName]),
[Total Sales] > 50000000
)
در اینجا برای هر مشتری، [Total Sales] در Context مربوط به آن مشتری ارزیابی میشود.
این نوع محاسبات در تحلیل مشتریان بسیار کاربردی است.
مثلاً میتوان از آن برای تحلیل:
- مشتریان ارزشمند
- مشتریان وفادار
- مشتریان کمخرید
- مشتریان غیرفعال
- مشتریان با خرید بالا
استفاده کرد.
Context Transition و Measure
یک نکته ظریف اما بسیار مهم:
Measureها رفتار متفاوتی با عبارتهای ساده DAX دارند.
هنگامی که یک Measure را در یک Context خاص فراخوانی میکنیم، Power BI آن Measure را در همان Context ارزیابی میکند.
به همین دلیل است که یک Measure مانند:
Total Sales =
SUM(Sales[Amount])
در یک Matrix میتواند برای هر شهر یا محصول مقدار متفاوتی نمایش دهد.
فرمول یکی است، اما Context متفاوت است.
این موضوع پایه بسیاری از قابلیتهای تحلیلی Power BI است.
آیا Context Transition همیشه اتفاق میافتد؟
خیر.
نباید این مفهوم را به شکل زیر حفظ کنیم:
«هر جا Row Context داریم، حتماً Context Transition اتفاق میافتد.»
Context Transition به شرایط اجرای CALCULATE و نحوه ارزیابی عبارت مربوط است.
قاعده مهم برای شروع این است:
CALCULATE میتواند Row Context را به Filter Context تبدیل کند.
پس اگر در یک فرمول با Row Context و CALCULATE مواجه شدید، باید به Context Transition فکر کنید.
یک مثال برای مقایسه
فرض کنید در جدول Customer هستیم.
حالت اول
Customer Sales =
[Total Sales]
حالت دوم
Customer Sales =
CALCULATE(
[Total Sales]
)
در حالت دوم CALCULATE وارد فرآیند محاسبه میشود و میتواند Row Context مربوط به مشتری جاری را به Filter Context تبدیل کند.
این تفاوت یکی از مثالهای کلاسیک برای آموزش Context Transition است.
Context Transition را چگونه در ذهن خودمان نگه داریم؟
برای اینکه این مفهوم فراموش نشود، یک تصویر ذهنی ساده داشته باشید:
فرض کنید DAX روی یک ردیف ایستاده است.
مثلاً:
CustomerID = 125
این اطلاعات در Row Context وجود دارد.
حالا CALCULATE میگوید:
«اطلاعات ردیف جاری را به فیلتر تبدیل کن.»
در نتیجه چیزی شبیه این اتفاق رخ میدهد:
CustomerID = 125
↓
Row Context
↓
CALCULATE
↓
CustomerID = 125 بهعنوان Filter
↓
محاسبه فروش مشتری 125
این مدل ذهنی برای شروع یادگیری بسیار مفید است.
اشتباه رایج؛ حفظ کردن Context Transition بدون فهم Context
یکی از مشکلات آموزش DAX این است که بعضی کاربران مستقیماً سراغ تعریف Context Transition میروند، بدون اینکه Row Context و Filter Context را بهخوبی بفهمند.
در این حالت اصطلاحات زیاد میشوند:
- Row Context
- Filter Context
- Context Transition
- CALCULATE
- Iterator
- Relationship
اما ارتباط بین آنها مشخص نیست.
پیشنهاد بهتر این است که این مفاهیم را به ترتیب یاد بگیرید:
Row Context
↓
Filter Context
↓
CALCULATE
↓
Context Transition
↓
Iteratorها
با این ترتیب، یادگیری بسیار منطقیتر خواهد بود.
یک تمرین عملی برای یادگیری Context Transition
برای تمرین یک مدل ساده شامل دو جدول بسازید:
جدول Customer
CustomerID
CustomerName
City
جدول Sales
SaleID
CustomerID
Product
Quantity
Amount
بین Customer و Sales یک Relationship ایجاد کنید.
سپس Measure زیر را بسازید:
Total Sales =
SUM(Sales[Amount])
در جدول Customer یک Calculated Column بسازید:
Customer Sales =
CALCULATE(
[Total Sales]
)
حالا CustomerName، Customer Sales و یک Measure فروش را در یک Visual قرار دهید.
نتایج را بررسی کنید.
سپس Relationship را بررسی کنید و ببینید چگونه تغییر مدل داده میتواند نتیجه محاسبات را تحت تأثیر قرار دهد.
هدف این تمرین حفظ فرمول نیست.
هدف این است که بتوانید توضیح دهید:
«چرا CALCULATE در اینجا باعث میشود مشتری جاری روی محاسبه فروش اثر بگذارد؟»
اگر بتوانید این سؤال را با زبان خودتان جواب دهید، مفهوم Context Transition را بهخوبی درک کردهاید.
ارتباط Context Transition با مقالههای قبلی
Context Transition یک موضوع مستقل نیست و با چند مفهوم قبلی DAX ارتباط مستقیم دارد.
اگر این مجموعه را به ترتیب دنبال میکنید، پیشنهاد میکنم این مسیر را داشته باشید:
Measure و Calculated Column
ابتدا تفاوت محاسبات ذخیرهشده و محاسبات پویا را یاد بگیرید.
SUM و SUMX
بعد با Iteratorها و محاسبات ردیفبهردیف آشنا شوید.
CALCULATE
سپس یاد بگیرید چگونه Context محاسبه تغییر میکند.
Row Context و Filter Context
بعد تفاوت این دو Context را درک کنید.
FILTER
سپس با فیلتر کردن Table Expressionها کار کنید.
Context Transition
حالا میتوانید ارتباط این مفاهیم را کنار هم ببینید.
این ترتیب برای کسی که میخواهد DAX را واقعاً بفهمد، بسیار بهتر از حفظ کردن فرمولهای پراکنده است.
جمعبندی
Context Transition یکی از مفاهیم مهم و در عین حال نسبتاً ظریف در DAX است.
به زبان ساده:
Row Context مربوط به ردیف جاری است.
Filter Context مشخص میکند چه دادههایی در محاسبه حضور داشته باشند.
و Context Transition فرآیندی است که در آن CALCULATE میتواند Row Context را به Filter Context تبدیل کند.
به همین دلیل فرمول:
CALCULATE(
[Total Sales]
)
در یک Row Context میتواند رفتاری کاملاً متفاوت با:
[Total Sales]
داشته باشد.
این موضوع مخصوصاً هنگام کار با:
- Calculated Column
- Iteratorها
- FILTER
- SUMX
- Measureهای پیچیده
- Relationshipها
- CALCULATE
اهمیت پیدا میکند.
اگر هدف شما فقط ساخت چند نمودار ساده در Power BI باشد، ممکن است مدتی بدون درک عمیق Context کارتان راه بیفتد؛ اما وقتی وارد DAX حرفهای شوید، درک Context دیگر یک موضوع فرعی نیست و به یکی از پایههای اصلی کار شما تبدیل میشود.
سؤالات متداول Context Transition در DAX
Context Transition در Power BI چیست؟
Context Transition فرآیندی در DAX است که طی آن CALCULATE میتواند Row Context موجود را به Filter Context تبدیل کند.
آیا CALCULATE باعث Context Transition میشود؟
CALCULATE میتواند هنگام اجرا در یک Row Context، Context Transition ایجاد کند.
Context Transition بیشتر کجا استفاده میشود؟
این مفهوم در Calculated Columnها، Iteratorها، Measureهای پیچیده و ترکیب توابعی مانند CALCULATE و FILTER اهمیت زیادی دارد.
آیا Row Context و Filter Context یکی هستند؟
خیر. Row Context به ردیف جاری مربوط است، در حالی که Filter Context مجموعه دادهای را که در محاسبه حضور دارد مشخص میکند.
آیا SUMX با Context Transition ارتباط دارد؟
SUMX یک Iterator است و Row Context ایجاد میکند. هنگامی که در این محیط از Measureها و CALCULATE استفاده میشود، درک Context Transition برای فهم رفتار محاسبه اهمیت پیدا میکند.
چرا Context Transition در DAX مهم است؟
زیرا بسیاری از محاسبات پیشرفته DAX بدون درک نحوه تبدیل Contextها بهدرستی قابل تحلیل و عیبیابی نیستند.

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