Thep Excel

CALCULATE – ฟังก์ชันเปลี่ยนบริบทการคำนวณ (หัวใจของ DAX)

เปลี่ยนบริบทการคำนวณและควบคุม Filter Context (หัวใจของ DAX)

ฟังก์ชันที่สำคัญที่สุดใน DAX ใช้ประเมิน Expression ภายใต้ Filter Context ที่ถูกปรับเปลี่ยน เข้าใจลึกซึ้งเรื่อง Context Transition, Filter Arguments (Table vs Boolean), และลำดับการประเมินผล (Order of Evaluation) เพื่อควบคุมการคำนวณได้อย่างแม่นยำ

=CALCULATE(Expression, [Filter1], [Filter2], ...)

By ThepExcel AI Agent
1 December 2025

Syntax & Arguments

=CALCULATE(Expression, [Filter1], [Filter2], ...)

Argument Type Required Default Description
Expression scalar Yes นิพจน์ที่ต้องการประเมินผล (เช่น Measure หรือสูตร Aggregation) จะถูกคำนวณเป็นลำดับสุดท้ายหลังจากเตรียม Context เสร็จแล้ว
Filter1, Filter2, … table/boolean Optional เงื่อนไขการกรอง ซึ่งแท้จริงแล้วคือ ‘ตาราง’ ที่จะนำไป intersect กับ Data Model หากใส่เป็น Boolean (Col=Val) จะถูกแปลงเป็น FILTER(ALL(Col), Col=Val)

How it works

Context Transition ใน Iterator

การใช้ CALCULATE ใน SUMX เพื่อให้เกิดการเปลี่ยน Row Context เป็น Filter Context ทำให้คำนวณค่าได้ถูกต้องตามแต่ละแถว

การจัดการตัวกรองที่ซับซ้อน (Complex Filtering)

การใช้ KEEPFILTERS เพื่อเพิ่มเงื่อนไขโดยไม่ล้างค่าเดิม หรือการใช้ FILTER(ALL(…)) เพื่อควบคุมการ Overwrite อย่างแม่นยำ

Time Intelligence แบบกำหนดเอง

การเขียนสูตรเปรียบเทียบช่วงเวลาโดยใช้ CALCULATE ร่วมกับตารางวันที่ เพื่อควบคุม Date Context

Examples

ตัวอย่างที่ 1: ความลับของ Boolean Filter (Overwrite)

นี่คือเหตุผลที่การใช้ Boolean Filter จึง 'เขียนทับ' (Overwrite) ตัวกรองเดิมเสมอ ถ้าอยากให้ 'ผสม' (Intersect) ต้องใช้ KEEPFILTERS ครอบ
DAX Formula:

=-- เขียนแบบย่อ (Boolean)
Total Red Sales = CALCULATE( [Sales], Product[Color] = "Red" )

-- เขียนแบบเต็ม (สิ่งที่ DAX ทำเบื้องหลัง)
Total Red Sales Full = CALCULATE(
    [Sales],
    FILTER( ALL( Product[Color] ), Product[Color] = "Red" )
)

Result:

ทั้งสองสูตรให้ผลลัพธ์เหมือนกัน คือยอดขายสีแดง โดยไม่สนใจว่า Slicer เดิมเลือกสีอะไร (เพราะ ALL)

ตัวอย่างที่ 2: Context Transition ใน Calculated Column

แม้สูตรจะเป็น SUM(Sales[Amount]) ธรรมดา แต่การมี CALCULATE (หรือการเรียกผ่าน Measure) จะเปลี่ยน Row Context (Customer ปัจจุบัน) ให้กลายเป็น Filter Context ผลลัพธ์จึงเป็นยอดขายเฉพาะของลูกค้ารายนั้น ไม่ใช่ยอดขายรวมทั้งบริษัท
DAX Formula:

-- สร้างในตาราง Customer
Customer Sales = CALCULATE( SUM( Sales[Amount] ) )

Result:

ยอดขายรวมของลูกค้า 'คนนั้นๆ' (ในแต่ละแถว)

ตัวอย่างที่ 3: แก้ปัญหา Measure ใน Filter Argument

DAX ไม่อนุญาตให้เกิด Context Transition ในขณะที่กำลังสร้าง Filter Argument แบบ Boolean (เพราะ Boolean ต้องถูกแปลงเป็น Table ก่อน) การใช้ตัวแปร (VAR) ช่วยให้ค่าถูกคำนวณให้เสร็จใน Context เดิมก่อน แล้วค่อยส่ง 'ค่าคงที่' เข้าไปใน Filter
DAX Formula:

=-- Incorrect: Cannot use CALCULATE/Measure directly in Boolean Filter
-- CALCULATE( [Sales], Product[Price] > [Avg Price] ) -- ERROR!

-- Correct: Pre-calculate value into a variable
VAR AvgPrice = [Avg Price]
RETURN
CALCULATE(
    [Sales],
    Product[Price] > AvgPrice
)

Result:

ยอดขายสินค้าที่มีราคาสูงกว่าราคาเฉลี่ย

FAQs

ทำไมใช้ Filter Argument ข้ามตารางไม่ได้ (Multiple Tables)?

ข้อจำกัดของ Syntax แบบ Boolean คือต้องอ้างอิงคอลัมน์จากตารางเดียวเท่านั้น เพราะเบื้องหลังมันใช้ ALL(Table[Col]) หากต้องการกรองหลายตารางพร้อมกัน ต้องใช้ฟังก์ชัน FILTER(…) เขียนเงื่อนไขเองอย่างชัดเจน

Context Transition เกิดขึ้นตอนไหน?

เกิดขึ้นหลังจากประเมิน Filter Arguments เสร็จแล้ว แต่อยู่ก่อนการ Apply Filters เข้าสู่ Context หลัก ทำให้ Explicit Filters (ที่ใส่ใน CALCULATE) สามารถ Overwrite ผลจาก Context Transition ได้

ความแตกต่างระหว่าง FILTER(Table, …) กับ FILTER(ALL(Column), …)?

FILTER(Table) จะสแกนและคืนค่าทั้งตาราง (Expanded Table) ซึ่งอาจมีผลข้างเคียงกับตารางที่ Relationship กันและช้ากว่า ส่วน FILTER(ALL(Column)) จะคืนค่าเฉพาะคอลัมน์เดียวที่ระบุ ซึ่งปลอดภัยและเร็วกว่าสำหรับการกรองแบบเจาะจง

Resources & Related

Additional Notes

CALCULATE คือฟังก์ชันที่ทรงพลังที่สุดและซับซ้อนที่สุดใน DAX ทำหน้าที่ประเมินผล Expression ภายใต้ บริบทตัวกรอง (Filter Context) ที่ถูกปรับเปลี่ยนใหม่ หากคุณเข้าใจ CALCULATE อย่างลึกซึ้ง คุณจะเข้าใจพฤติกรรมของ DAX ทั้งหมดครับ

ความจริงเกี่ยวกับ Filter Arguments

สิ่งสำคัญที่ต้องรู้คือ Filter Argument ทุกตัวใน CALCULATE คือ “ตาราง” (Table) เสมอ แม้ว่าคุณจะเขียนในรูปแบบ Boolean Expression (เช่น Product[Color] = "Red") ก็ตาม

เมื่อคุณเขียน:

CALCULATE( [Sales], 'Product'[Color] = "Red" )

DAX จะแปลงโค้ดนี้เบื้องหลัง (Internal Translation) เป็น:

CALCULATE(
    [Sales],
    FILTER( ALL( 'Product'[Color] ), 'Product'[Color] = "Red" )
)

จุดสังเกตที่สำคัญที่สุดคือฟังก์ชัน ALL ที่ถูกใส่เข้ามาอัตโนมัติ นี่คือสาเหตุว่าทำไมการเขียนแบบ Boolean ถึงเป็นการ “แทนที่” (Override) ตัวกรองเดิมเสมอ เพราะ ALL จะล้าง Filter เดิมของคอลัมน์นั้นทิ้งทั้งหมดก่อน แล้วค่อยใส่ “Red” เข้าไปใหม่

Context Transition (การเปลี่ยนบริบท)

Context Transition คือกระบวนการที่ CALCULATE เปลี่ยน Row Context (บริบทแถวปัจจุบัน) ให้กลายเป็น Filter Context (ตัวกรอง) ซึ่งจะเกิดขึ้นเมื่อ:

  • ใช้ CALCULATE ภายใน Calculated Column
  • ใช้ CALCULATE ภายใน Iterator Function (เช่น SUMX, FILTER)

พฤติกรรม: ค่าทั้งหมดใน “แถวปัจจุบัน” จะถูกเปลี่ยนเป็น Filter เพื่อกรองโมเดลข้อมูลก่อนทำการคำนวณ Expression
ข้อควรระวัง: การเรียกใช้ Measure ภายใน DAX expression จะมีการใส่ CALCULATE ครอบให้อัตโนมัติเสมอ ทำให้เกิด Context Transition โดยที่คุณอาจไม่รู้ตัว

ลำดับการทำงาน (Order of Evaluation)

เพื่อให้เข้าใจผลลัพธ์ที่ถูกต้อง คุณต้องทราบลำดับการทำงานภายในของ CALCULATE ดังนี้:

  1. Evaluate Filter Arguments: ประเมินค่าของ Filter Arguments ทั้งหมด ในบริบทเดิม (Original Context) ก่อนที่จะมีการเปลี่ยนแปลงใดๆ *ขั้นตอนนี้สำคัญมาก เพราะ Filter จะไม่ได้รับผลกระทบจาก Context Transition ที่เกิดจาก CALCULATE ตัวมันเอง
  2. Context Transition: ถ้าอยู่ใน Row Context, แถวปัจจุบันจะถูกแปลงเป็น Filter Context (Invalidate Row Context)
  3. Evaluate Modifiers: ฟังก์ชันปรับแต่งเช่น USERELATIONSHIP, CROSSFILTER, ALL* ถูกประเมิน
  4. Apply Filters: นำผลลัพธ์จากข้อ 1 มาใช้กับ Filter Context (โดยปกติจะใช้ AND Logic และ Overwrite ตัวกรองที่มีอยู่ในคอลัมน์เดียวกัน)
  5. Evaluate Expression: สุดท้าย จึงคำนวณ Expression หลักภายใต้บริบทใหม่ที่สมบูรณ์แล้ว

Leave a Reply

Your email address will not be published. Required fields are marked *