Thep Excel

SUMX – Iterator Function สำหรับคำนวณผลรวมแบบ Row-by-Row ใน DAX

SUMX เป็น iterator function ที่ทรงพลังใน DAX ออกแบบมาเพื่อวนลูปทีละแถวในตารางที่กำหนด แล้วคำนวณ expression ที่ซับซ้อนสำหรับแต่ละแถวก่อนนำผลลัพธ์ทั้งหมดมารวมกัน ต่างจาก SUM ที่รวมเฉพาะค่าใน column เดียว SUMX สร้าง row context สำหรับแต่ละแถว ทำให้สามารถคำนวณ expression อย่าง Quantity × Price หรือใช้ RELATED ดึงข้อมูลข้ามตารางได้ มีกลไก context transition อัตโนมัติเมื่อเจอ measure ในนั้น เหมาะสำหรับการคำนวณซับซ้อนระดับแถวข้อมูล ประหยัดพื้นที่ model เพราะไม่ต้องสร้าง calculated column แต่ช้ากว่า SUM และไม่รองรับ DirectQuery mode ใน calculated columns หรือ RLS rules

=SUMX(<table>, <expression>)

By ThepExcel AI Agent
18 December 2025

Function Metrics


Popularity
9/10

Difficulty
5/10

Usefulness
9/10

Syntax & Arguments

=SUMX(<table>, <expression>)

Argument Type Required Default Description
table table Yes ตารางที่ต้องการให้ SUMX iterate ทีละแถว สามารถเป็นชื่อตารางโดยตรง (เช่น Sales, Products) หรือ expression ที่ return table (เช่น FILTER, CALCULATETABLE, VALUES, SUMMARIZE) SUMX จะสร้าง row context ขึ้นมาใหม่สำหรับแต่ละแถวในตารางนี้ ทำให้สามารถอ้างถึงค่าในคอลัมน์ของแถวนั้นๆ ได้โดยตรงในระหว่างการ evaluate expression ตาราง argument นี้จะถูก evaluate ภายใน filter context ที่มีอยู่ก่อนจึงจะเริ่ม iterate
expression scalar Yes Expression หรือสูตรคำนวณที่ต้องการให้ evaluate สำหรับแต่ละแถวในตาราง สามารถเป็นการคูณคอลัมน์ (เช่น Sales[Quantity] * Sales[UnitPrice]) การใช้ RELATED ดึงข้อมูลข้ามตาราง (เช่น Sales[Quantity] * RELATED(Products[Cost])) หรือการเรียกใช้ measure (เช่น [Unit Profit] ซึ่งจะเกิด context transition อัตโนมัติ) Expression นี้ทำงานภายใน row context ที่ SUMX สร้างขึ้นสำหรับแต่ละแถว ทำให้สามารถอ้างถึงค่าในคอลัมน์ของแถวปัจจุบันได้ ผลลัพธ์ที่ได้จากแต่ละแถวจะถูกรวมกันเป็นผลลัพธ์สุดท้าย ตาม Microsoft Learn “Only numeric values are counted. Blanks, logical values, and text are ignored”

How it works

คำนวณยอดขายรวมจาก Quantity × Price โดยไม่ต้องสร้าง Calculated Column

เมื่อไม่มี calculated column สำหรับเก็บยอดเงินไว้ในตาราง สามารถใช้ SUMX คูณจำนวนกับราคาในแต่ละแถวแล้วรวมผลลัพธ์ได้ทันที โดยไม่ต้องสร้าง calculated column ใหม่ที่จะเปลืองพื้นที่ใน data model วิธีนี้ยืดหยุ่นกว่าเพราะสามารถเปลี่ยนสูตรคำนวณได้ตลอดเวลา นี่คือ use case ที่พบบ่อยที่สุดของ SUMX

หาผลรวมจากตารางที่กรองด้วย FILTER ก่อน Iterate

ใช้ร่วมกับ FILTER เพื่อกรองเฉพาะแถวที่ตรงเงื่อนไข เช่น สินค้าในหมวดหมู่ใดหมวดหมู่หนึ่ง ลูกค้าจากประเทศที่กำหนด หรือรายการที่มียอดเกินจำนวนที่กำหนด ก่อนที่จะให้ SUMX iterate และคำนวณ Pattern SUMX(FILTER(…), …) เป็นหนึ่งใน pattern ที่ใช้บ่อยที่สุดใน DAX เพราะให้ control ทั้ง filter context และ row context ไปพร้อมกัน

ดึงข้อมูลจาก Related Table ด้วย RELATED เพื่อคำนวณข้ามตาราง

ใช้ RELATED ภายใน expression ของ SUMX เพื่อเข้าถึงข้อมูลจากตารางที่มีความสัมพันธ์ เช่น ดึงราคาต้นทุนจาก Products table มาคูณกับจำนวนใน Sales table หรือดึงอัตราแลกเปลี่ยนจาก Currency table วิธีนี้ช่วยให้สามารถคำนวณข้ามตารางได้โดยไม่ต้องสร้าง calculated column ใหม่ที่จะเพิ่มขนาดไฟล์ RELATED ทำงานได้เฉพาะใน row context ซึ่ง SUMX สร้างให้อยู่แล้ว

Iterate Measure ที่มีอยู่แล้วด้วย Context Transition

ใช้ measure ที่สร้างไว้แล้วเป็น expression ภายใน SUMX โดยจะเกิด context transition อัตโนมัติที่แปลง row context เป็น filter context ทันที เหมาะสำหรับการคำนวณที่ซับซ้อนหลายขั้นตอน เช่น การรวม measure ที่คำนวณกำไรของแต่ละสินค้า หรือการรวม measure ที่มีการคำนวณส่วนลดตามเงื่อนไข ทำให้สามารถนำ business logic ที่ซับซ้อนมาใช้ร่วมกับ SUMX ได้อย่างมีประสิทธิภาพ

Examples

ตัวอย่างที่ 1: Foundation – คำนวณยอดขายรวมโดยคูณ Quantity × UnitPrice
Total Sales = SUMX( Sales, Sales[Quantity] * Sales[UnitPrice] ) // Context: Sales table มี columns: Quantity และ UnitPrice // Data model: Sales[Quantity] เก็บจำ…
นี่คือ use case พื้นฐานที่เจอบ่อยที่สุดของ SUMX ครับ
.
SUMX จะวนลูปไปทีละแถวในตาราง Sales และสร้าง row context สำหรับแต่ละแถว ทำให้เราอ้างถึง Sales[Quantity] และ Sales[UnitPrice] ของแถวนั้นๆ ได้โดยตรง จากนั้นคูณค่าทั้งสองเพื่อได้ยอดเงินสำหรับแถวนั้น
.
เมื่อวนครบทุกแถว SUMX จะรวมผลลัพธ์ทั้งหมดเป็นยอดขายรวม
.
วิธีนี้ดีกว่าการสร้าง calculated column ใหม่เพราะไม่เปลืองพื้นที่ใน data model และปรับ formula ได้ง่าย แต่ถ้าคุณมี calculated column Amount อยู่แล้ว การใช้ SUM(Sales[Amount]) จะเร็วกว่ามากครับ 😎
DAX Formula:

Total Sales = 
SUMX(
    Sales,
    Sales[Quantity] * Sales[UnitPrice]
)

// Context: Sales table มี columns: Quantity และ UnitPrice
// Data model: Sales[Quantity] เก็บจำนวนสินค้า, Sales[UnitPrice] เก็บราคาต่อหน่วย
//
// ตัวอย่างข้อมูลใน Sales table:
// Quantity | UnitPrice
// 10       | 50
// 5        | 100
// 8        | 75
//
// SUMX iterate แต่ละแถว:
// Row 1: 10 * 50 = 500
// Row 2: 5 * 100 = 500
// Row 3: 8 * 75 = 600
// Result: 500 + 500 + 600 = 1,600

Result:

1,600 (ผลรวมยอดขายทั้งหมดจากการคูณจำนวนกับราคาในแต่ละแถว)

ตัวอย่างที่ 2: Practical – กรองด้วย CALCULATE แล้วใช้ SUMX คำนวณ
// ✅ วิธีถูก: กรองที่ Dimension Table โดยตรงด้วย CALCULATE Electronics Sales = CALCULATE( SUMX( Sales, Sales[Quantity] * Sales[UnitPrice] ), Products[Category]…
⚠️ Golden Rule: Filter Columns, Not Tables!
.
✅ วิธีถูก: ใช้ CALCULATE ครอบ SUMX แล้วกรองที่ Products[Category] โดยตรง DAX Engine จะ optimize ให้อัตโนมัติ เร็วกว่า 100+ เท่า และถูกต้อง
.
❌ วิธีผิด: FILTER(Sales, RELATED(Products[Category]) = "Electronics") ต้องวนลูปทุกแถวใน Fact Table และกรอง "expanded table" ที่อาจให้ผลผิด
.
ส่วนตัวผมเคยเห็นหลายคนใช้ FILTER + RELATED แบบผิดๆ เพราะคิดว่าต้องกรองที่ Fact Table ทั้งที่จริงๆ แค่ใช้ CALCULATE กับ Boolean Expression ก็พอครับ! 😎
DAX Formula:

// ✅ วิธีถูก: กรองที่ Dimension Table โดยตรงด้วย CALCULATE
Electronics Sales = 
CALCULATE(
    SUMX(
        Sales,
        Sales[Quantity] * Sales[UnitPrice]
    ),
    Products[Category] = "Electronics"
)

// ❌ หลีกเลี่ยง: FILTER(Sales, RELATED(...)) ช้ามากและอาจให้ผลผิด!

// Context: Sales table มี relationship กับ Products table (many-to-one)
// Data model: 
//   Sales: OrderID, ProductID, Quantity, UnitPrice
//   Products: ProductID, ProductName, Category
//   Relationship: Sales[ProductID] → Products[ProductID]
//
// ตัวอย่างข้อมูล:
// Sales table:          Products table:
// ProductID | Qty | Price    ProductID | Category
// 101       | 10  | 50       101       | Electronics
// 102       | 5   | 30       102       | Clothing
// 103       | 8   | 75       103       | Electronics
//
// CALCULATE กรองเฉพาะ Electronics:
// Row 1: (10 * 50 = 500) ✅ included
// Row 2: (5 * 30 = 150) ❌ excluded (Clothing)
// Row 3: (8 * 75 = 600) ✅ included
// Result: 500 + 600 = 1,100

Result:

1,100 (ยอดขายรวมเฉพาะสินค้าในหมวด Electronics)

ตัวอย่างที่ 3: Advanced – คำนวณกำไรสุทธิด้วย VAR และ RELATED
Total Profit = SUMX( Sales, VAR Revenue = Sales[Quantity] * Sales[UnitPrice] VAR Cost = Sales[Quantity] * RELATED(Products[UnitCost]) RETURN Revenue - Cost ) //…
นี่คือ advanced technique ที่ผมชอบมาก คือการใช้ VAR…RETURN pattern ภายใน SUMX expression ครับ 😎
.
ภายใน SUMX เราสร้าง VAR Revenue คำนวณยอดขายจาก Quantity × UnitPrice และสร้าง VAR Cost คำนวณต้นทุนจาก Quantity × RELATED(Products[UnitCost]) โดยใช้ RELATED ดึงราคาต้นทุนจาก Products table
.
จากนั้น RETURN ผลต่าง Revenue – Cost เป็นกำไรสำหรับแถวนั้น แล้ว SUMX จะรวมกำไรจากทุกแถวเป็นกำไรรวม
.
การใช้ VAR ทำให้แต่ละส่วนของสูตรมีชื่อที่มีความหมายชัดเจน อ่านง่าย debug ได้ง่าย และอาจช่วยเรื่อง performance ด้วย (DAX อาจ cache intermediate result ได้) 💡
DAX Formula:

Total Profit = 
SUMX(
    Sales,
    VAR Revenue = Sales[Quantity] * Sales[UnitPrice]
    VAR Cost = Sales[Quantity] * RELATED(Products[UnitCost])
    RETURN
        Revenue - Cost
)

// Context: Sales table มี relationship กับ Products table
// Data model:
//   Sales: OrderID, ProductID, Quantity, UnitPrice
//   Products: ProductID, ProductName, UnitCost
//   Relationship: Sales[ProductID] → Products[ProductID]
//
// ตัวอย่างข้อมูล:
// Sales table:          Products table:
// ProductID | Qty | Price    ProductID | UnitCost
// 101       | 10  | 50       101       | 30
// 102       | 5   | 100      102       | 60
// 103       | 8   | 75       103       | 45
//
// SUMX iterate:
// Row 1: Revenue = 10 * 50 = 500, Cost = 10 * 30 = 300, Profit = 200
// Row 2: Revenue = 5 * 100 = 500, Cost = 5 * 60 = 300, Profit = 200
// Row 3: Revenue = 8 * 75 = 600, Cost = 8 * 45 = 360, Profit = 240
// Result: 200 + 200 + 240 = 640

Result:

640 (กำไรสุทธิรวมจากทุกรายการขาย)

ตัวอย่างที่ 4: Complex – Iterate Measure ด้วย Context Transition และ VALUES
// สมมติว่ามี measure อยู่แล้ว: // [Total Sales Per Product] = SUM(Sales[Amount]) Sales By Product = VAR ProductList = VALUES(Products[ProductName]) VAR SalesBy…
นี่เป็น advanced pattern ที่เจ๋งมากครับ คือการใช้ VALUES ร่วมกับ SUMX 😎
.
VALUES สร้างตารางที่มีเฉพาะค่าที่ไม่ซ้ำ (distinct values) ของ ProductName จากนั้น SUMX วนลูปแต่ละ product และ evaluate measure [Total Sales Per Product]
.
สิ่งสำคัญที่สุดคือ… เมื่อ SUMX เจอ measure ภายใน expression จะเกิด **context transition** อัตโนมัติ! Row context (ProductName = "Laptop") จะถูกแปลงเป็น filter context CALCULATE([Total Sales Per Product], Products[ProductName] = "Laptop") ทำให้ measure คำนวณถูกต้องสำหรับแต่ละ product แยกกัน
.
ถ้าไม่มี context transition measure จะคำนวณยอดรวมทั้งหมดซ้ำๆ ซึ่งผิดพลาด 😅
.
ส่วนตัวผมชอบ pattern นี้มากเมื่อต้อง aggregate measure ในระดับ granularity ที่ต่างไป การใช้ VALUES ยังช่วย optimize performance ด้วย เพราะลดจำนวนแถวที่ต้อง iterate จากทุกแถวใน fact table เหลือเฉพาะแถวที่ unique ใน dimension table 💡
DAX Formula:

// สมมติว่ามี measure อยู่แล้ว:
// [Total Sales Per Product] = SUM(Sales[Amount])

Sales By Product = 
VAR ProductList = VALUES(Products[ProductName])
VAR SalesByProduct = 
    SUMX(
        ProductList,
        [Total Sales Per Product]
    )
RETURN
    SalesByProduct

// Context: VALUES สร้างตารางที่มีเฉพาะ ProductName ที่ไม่ซ้ำ
// Data model:
//   Sales: OrderID, ProductID, Amount
//   Products: ProductID, ProductName
//   Measure: [Total Sales Per Product] = SUM(Sales[Amount])
//
// ตัวอย่าง VALUES(Products[ProductName]):
// ProductName
// "Laptop"
// "Mouse"
// "Keyboard"
//
// SUMX iterate แต่ละ product:
// Row 1: ProductName = "Laptop"
//   → Context transition →
//   CALCULATE([Total Sales Per Product], Products[ProductName] = "Laptop")
//   → Result: 5,000
// Row 2: ProductName = "Mouse"
//   → Context transition →
//   CALCULATE([Total Sales Per Product], Products[ProductName] = "Mouse")
//   → Result: 1,500
// Row 3: ProductName = "Keyboard"
//   → Context transition →
//   CALCULATE([Total Sales Per Product], Products[ProductName] = "Keyboard")
//   → Result: 2,000
// Result: 5,000 + 1,500 + 2,000 = 8,500

Result:

8,500 (ผลรวมยอดขายทั้งหมดจากการรวม measure ของแต่ละ product)

FAQs

ทำไมไม่ใช้ SUM แทน SUMX? SUMX ช้ากว่าไหม?

ช้ากว่าครับ 😅 เพราะ SUMX ต้องวนลูปทีละแถวและคำนวณ expression ในแต่ละแถวโดยใช้ formula engine ในขณะที่ SUM ประมวลผลโดย storage engine โดยตรง
.
ถ้าคุณมี calculated column ที่เก็บยอดเงินไว้แล้ว (เช่น Sales[Amount] = Quantity × Price) การใช้ SUM(Sales[Amount]) จะเร็วกว่ามาก แต่ถ้าไม่มี calculated column นั้น การใช้ SUMX จะประหยัดพื้นที่ data model มากกว่า
.
ดังนั้นต้องชั่งน้ำหนักระหว่าง performance (SUM + calculated column) กับขนาดไฟล์ (SUMX โดยตรง)
.
ส่วนตัวผมแนะนำให้ใช้ SUMX ก่อน ถ้าไม่มีปัญหาความเร็ว แล้วค่อยสร้าง calculated column + SUM เฉพาะเมื่อต้องการ optimize performance สูงสุด 💡

SUMX สร้าง row context หรือ filter context?

SUMX สร้าง **row context** ครับ สำหรับ expression ที่อยู่ภายในขณะที่วนลูปแต่ละแถว ทำให้เราอ้างถึงค่าในคอลัมน์ของแถวนั้นๆ ได้โดยตรง เช่น Sales[Quantity] จะเข้าถึงค่าในแถวปัจจุบัน
.
แต่ถ้า expression นั้นเป็น measure ที่สร้างไว้แล้ว (เช่น [Total Sales]) จะเกิด **context transition** อัตโนมัติ! Row context จะถูกแปลงเป็น filter context ทันที โดยการสร้าง implicit CALCULATE ครอบ measure นั้นไว้
.
นี่คือเหตุผลที่ SUMX สามารถใช้ measure เป็น expression ได้โดยไม่มีปัญหา ในขณะที่ SUM ปกติใช้ได้เฉพาะ column reference โดยตรงเท่านั้น 😎

เมื่อไหร่ควรใช้ SUMX แทน CALCULATE?

ใช้ SUMX เมื่อต้องการวนลูปทีละแถวเพื่อคำนวณ expression ที่ต่างกันหรือซับซ้อนในแต่ละแถว เช่น การคูณ Quantity กับ Price หรือการใช้ RELATED ดึงข้อมูลจากตารางอื่นมาคำนวณ
.
ส่วน CALCULATE ใช้เมื่อต้องการเปลี่ยน filter context เพื่อหาค่า aggregation แบบเดียวทั้งหมด เช่น SUM ยอดขายเฉพาะหมวด Electronics โดยไม่ต้องวนลูปทีละแถว
.
หลายครั้งเราใช้ทั้งสองร่วมกัน เช่น SUMX(FILTER(…), …) หรือ CALCULATE(SUMX(…), …)
.
กฎง่ายๆ คือ ถ้าต้องการคำนวณ expression ที่ต่างกันในแต่ละแถว → ใช้ SUMX ถ้าแค่ต้องการเปลี่ยน filter context เพื่อ aggregate แบบเดียว → ใช้ CALCULATE 💡

ทำไม SUMX ใช้ร่วมกับ VALUES ได้บ่อย?

VALUES เป็นฟังก์ชันที่สร้างตารางที่มีเฉพาะค่าที่ไม่ซ้ำกัน (distinct values) ซึ่งเหมาะกับการใช้ร่วมกับ SUMX มากครับ มี 2 เหตุผลหลัก:
.
**(1) Performance Optimization** ลดจำนวนแถวที่ต้องวนลูปจากทุกแถวใน fact table (หลายล้านแถว) เหลือเฉพาะค่าที่ unique (หลายพันค่า) ทำให้เร็วขึ้นมาก 🚀 โดยเฉพาะเมื่อใช้ร่วมกับ measure ที่ trigger context transition
.
**(2) Granularity Control** บังคับให้ SUMX วนลูปในระดับ granularity ที่ต้องการ เช่น SUMX(VALUES(Products[ProductName]), [Total Sales]) จะวนลูปเฉพาะ product ที่ unique แล้ว evaluate [Total Sales] สำหรับแต่ละ product
.
Pattern SUMX + VALUES เป็น best practice ที่ใช้บ่อยมากเมื่อต้องการ aggregate measure ในระดับ dimension table แทน fact table 😎

ควรใช้ SUMX ร่วมกับ VAR…RETURN อย่างไร?

การใช้ VAR…RETURN ร่วมกับ SUMX เป็น best practice สำหรับ measure ที่ซับซ้อนครับ เพราะช่วยให้ formula อ่านง่ายและบำรุงรักษาได้ง่ายขึ้น มี 2 แนวทางหลัก:
.
**(1) VAR ภายนอก SUMX** ใช้เก็บตารางที่ผ่านการกรองจาก FILTER, CALCULATETABLE หรือ VALUES ไว้ก่อน แล้วส่งให้ SUMX วนลูป วิธีนี้ลดการคำนวณซ้ำและทำให้ code อ่านง่าย
.
เช่น `VAR FilteredSales = FILTER(Sales, …) RETURN SUMX(FilteredSales, …)`
.
**(2) VAR ภายใน SUMX expression** ใช้เก็บ intermediate result ภายใน expression ทำให้สูตรซับซ้อนอ่านง่าย
.
เช่น `SUMX(Sales, VAR Revenue = … VAR Cost = … RETURN Revenue – Cost)`
.
ส่วนตัวผมชอบใช้ VAR มากเพราะทำให้แต่ละขั้นตอนมีชื่อที่มีความหมายชัดเจน debug ได้ง่าย และอาจช่วยเรื่อง performance ด้วยนะครับ 💡

SUMX ใช้ได้ใน DirectQuery mode หรือไม่?

ใช้ได้ครับ แต่มีข้อจำกัดสำคัญที่ต้องระวัง ⚠️
.
ตาม Microsoft Learn ระบุชัดเจนว่า SUMX “is not supported for use in DirectQuery mode when used in calculated columns or row-level security (RLS) rules” ซึ่งหมายความว่า:
.
❌ **(1) Calculated Columns** ใช้ SUMX ไม่ได้ใน DirectQuery mode
❌ **(2) RLS Rules** ใช้ SUMX ไม่ได้ใน DirectQuery mode
✅ **(3) Measures** ใช้ SUMX ได้ตามปกติใน DirectQuery mode
.
ดังนั้นถ้าคุณใช้ DirectQuery ต้องระวังว่าจะใช้ SUMX ที่ไหน และควรพิจารณาใช้ SUM กับ calculated column แทนถ้าเป็นไปได้ นี่เป็นข้อจำกัดสำคัญที่ต้องคำนึงถึงเมื่อออกแบบ data model สำหรับ DirectQuery นะครับ

SUMX จัดการกับ blank values และ non-numeric data อย่างไร?

ตาม Microsoft Learn ระบุว่า “Only numeric values are counted. Blanks, logical values, and text are ignored” ซึ่งหมายความว่า SUMX จะประมวลผลเฉพาะค่าตัวเลขเท่านั้นครับ
.
ค่าประเภทอื่นๆ จะถูกข้าม (ignore) โดยอัตโนมัติ:
• Blank values → ข้าม (ไม่นับรวมในผลลัพธ์)
• Logical values (TRUE/FALSE) → ข้าม
• Text values → ข้าม
.
ดังนั้นถ้า expression ของคุณคำนวณออกมาเป็น blank หรือ text ใน row ใดๆ row นั้นจะไม่มีส่วนร่วมในผลรวมสุดท้าย
.
นี่ต่างจาก Excel ที่อาจ treat blank เป็น 0 นะครับ ใน DAX blank จะถูกข้ามโดยสมบูรณ์ 💡

Resources & Related

Additional Notes

SUMX เป็น iterator function ที่ทรงพลังที่สุดตัวหนึ่งใน DAX ครับ 😎
.
มันแตกต่างจาก SUM อย่างสิ้นเชิง… ถ้า SUM รวมค่าใน column เดียวโดยตรง SUMX จะ iterate ทีละแถวในตารางที่กำหนด แล้ว evaluate expression สำหรับแต่ละแถวก่อนนำผลลัพธ์ทั้งหมดมารวมกัน
.
ความสามารถนี้ทำให้ SUMX เหมาะอย่างยิ่งสำหรับการคำนวณที่ซับซ้อนในระดับแถวข้อมูล เช่น การคูณ Quantity × Price การใช้ RELATED ดึงข้อมูลข้ามตาราง หรือการคำนวณตาม business logic ที่ต้องการ row context

Iterator Pattern และ Row Context

SUMX เป็น iterator function ที่สร้าง row context ขึ้นมาใหม่สำหรับแต่ละแถวที่ iterate ผ่าน ตามที่ Microsoft Learn อธิบายไว้ว่า “The function evaluates the expression for each row of the table”
.
ซึ่งหมายความว่าเมื่อ SUMX ทำงาน มันจะ scan table ทีละแถว และสร้าง row context ที่ทำให้เราสามารถอ้างถึงค่าในคอลัมน์ต่างๆ ของแถวปัจจุบันได้โดยตรง เช่น Sales[Quantity] * Sales[UnitPrice] ซึ่งคูณจำนวนกับราคาในแถวนั้นๆ นี่คือสิ่งที่ SUM ทำไม่ได้ครับ 💡

กระบวนการทำงานของ SUMX มี 3 ขั้นตอนหลัก:
.
**(1)** Evaluate table argument ภายใน filter context ที่มีอยู่เพื่อกำหนดว่าจะ iterate แถวไหนบ้าง
**(2)** สำหรับแต่ละแถว สร้าง row context ขึ้นมาแล้ว evaluate expression argument ภายใน row context นั้น
**(3)** รวมผลลัพธ์ทั้งหมดจากทุกแถวเป็นค่าสุดท้าย
.
ตาม DAX.guide อธิบายไว้ว่า “SUMX returns the sum of an expression evaluated for each row in a table” ซึ่งกลไกนี้ทำให้ SUMX แตกต่างจาก SUM อย่างสิ้นเชิงครับ

ความแตกต่างระหว่าง SUMX และ SUM

มาดูความแตกต่างกันครับ ตาม DAX.guide ได้อธิบายไว้อย่างชัดเจนว่า “SUM works only with columns in the model” ในขณะที่ SUMX สามารถ evaluate expression ที่ซับซ้อนได้:

  • SUM: รวมค่าใน column เดียวโดยตรง ไม่สามารถคำนวณ expression ได้ ทำงานใน filter context และประมวลผลโดย storage engine จึงเร็วกว่ามาก เหมาะกับการรวม column ที่มีค่าเก็บไว้แล้วใน data model
  • SUMX: Iterate แต่ละแถวเพื่อ evaluate expression ที่ซับซ้อน เช่น Sales[Quantity] * Sales[UnitPrice] หรือ Sales[Quantity] * RELATED(Products[Cost]) ยืดหยุ่นกว่าแต่ใช้ formula engine จึงช้ากว่า SUM เล็กน้อย
  • Variable Iteration: ตาม DAX.guide “SUMX is needed to iterate the content of variables since SUM only works with columns in the model” หมายความว่าถ้าคุณสร้าง table variable ด้วย FILTER หรือ CALCULATETABLE คุณต้องใช้ SUMX เท่านั้น SUM ไม่สามารถใช้กับ variable ได้

Context Transition ใน SUMX

นี่เป็นเรื่องสำคัญมากที่ต้องเข้าใจครับ… เมื่อ expression ภายใน SUMX เป็น measure ที่สร้างไว้แล้ว จะเกิดกลไก context transition อัตโนมัติ
.
โดย DAX จะแปลง row context เป็น filter context ทันทีผ่านการสร้าง implicit CALCULATE ครอบ measure นั้นไว้ ตัวอย่างเช่น SUMX(Products, [Total Sales]) เมื่อ iterate แต่ละ product จะแปลง row context (Products[ProductName] = “Product A”) ให้กลายเป็น CALCULATE([Total Sales], Products[ProductName] = “Product A”) โดยอัตโนมัติ
.
ทำให้ measure คำนวณถูกต้องสำหรับแต่ละ product แยกกัน นี่คือเหตุผลสำคัญที่ SUMX สามารถใช้ measure เป็น expression ได้โดยไม่มีปัญหา 😎

อย่างไรก็ตาม context transition มีค่าใช้จ่าย (overhead) ที่ไม่น้อย ดังนั้นควรใช้อย่างระมัดระวังกับตารางขนาดใหญ่นะครับ ⚠️

DirectQuery Limitations

เรื่องนี้ต้องระวังครับ… ตาม Microsoft Learn ระบุไว้อย่างชัดเจนว่า SUMX “is not supported for use in DirectQuery mode when used in calculated columns or row-level security (RLS) rules”
.
ซึ่งหมายความว่าถ้าคุณใช้ DirectQuery mode คุณไม่สามารถใช้ SUMX ใน calculated column หรือ RLS rules ได้ แต่สามารถใช้ใน measure ได้ตามปกติ
.
นี่เป็นข้อจำกัดสำคัญที่ต้องคำนึงถึงเมื่อออกแบบ data model สำหรับ DirectQuery ครับ

เมื่อไหร่ควรใช้ SUMX

คุณควรใช้ SUMX เมื่อ:

  • ต้องการคำนวณ expression ที่ซับซ้อนในระดับ row context โดยตรง เช่น Quantity × Price โดยไม่มี calculated column ที่เก็บผลลัพธ์ไว้แล้ว วิธีนี้ประหยัดพื้นที่ใน data model มากครับ 💡
  • ต้องการใช้ RELATED เพื่อเข้าถึงข้อมูลจาก related table เช่น ดึงราคาต้นทุนจาก Products table มาคูณกับจำนวนใน Sales table
  • ต้องการ iterate table variable ที่สร้างจาก FILTER หรือ CALCULATETABLE เพราะ SUM ทำงานได้เฉพาะกับ column ใน model เท่านั้น
  • ต้องการรวมผลลัพธ์จาก measure ที่สร้างไว้แล้ว โดยให้ context transition เกิดขึ้นอัตโนมัติ
  • ต้องการหลีกเลี่ยงการสร้าง calculated column ใหม่ที่จะเพิ่มขนาดไฟล์ data model

SUMX เป็นส่วนหนึ่งของตระกุล X Functions (iterator functions) ใน DAX ซึ่งรวมถึง AVERAGEX, MAXX, MINX, COUNTX และ CONCATENATEX ซึ่งทั้งหมดมี row context behavior และ context transition เหมือนกัน
.
เมื่อคุณเข้าใจ SUMX แล้ว คุณจะสามารถใช้ X Functions อื่นๆ ได้อย่างมีประสิทธิภาพทันที ส่วนตัวผมว่านี่เป็นหนึ่งในฟังก์ชันที่สำคัญที่สุดที่ต้องเชี่ยวชาญใน DAX เลยครับ 😎

Leave a Reply

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