SUMMARIZE สร้างตารางสรุปโดยจัดกลุ่มข้อมูลตามคอลัมน์ที่กำหนด คล้าย GROUP BY ใน SQL หรือ Pivot Table ใน Excel คืนค่าตารางที่มีหนึ่งแถวต่อหนึ่ง unique combination ของคอลัมน์ที่เลือก สามารถอ้างถึงคอลัมน์จาก related table ได้โดยตรงโดยไม่ต้องใช้ RELATED มักใช้สร้าง virtual table ใน measure เพื่อทำ intermediate calculations ก่อนใช้ iterator functions อย่าง SUMX, AVERAGEX คำนวณต่อ ⚠️ Best Practice: ใช้ ADDCOLUMNS ครอบ SUMMARIZE แทนการใส่ extension columns ตรงๆ เพื่อ performance และ filter context control ที่ดีกว่า สำหรับ calculated table แนะนำใช้ SUMMARIZECOLUMNS แทนเนื่องจากมี performance ดีกว่าอย่างมาก
=SUMMARIZE(<table>, <groupBy_columnName>[, <groupBy_columnName>]...)
=SUMMARIZE(<table>, <groupBy_columnName>[, <groupBy_columnName>]...)
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
| table | table | Yes | ตารางข้อมูลที่ต้องการจัดกลุ่มและสรุป สามารถเป็นชื่อตารางโดยตรง หรือ table expression จากฟังก์ชันอื่นเช่น FILTER (กรองก่อนจัดกลุ่ม), ALL (ดึงข้อมูลทั้งหมดโดยไม่คำนึงถึง filter context), หรือ CALCULATETABLE (ปรับเปลี่ยน filter context ก่อนจัดกลุ่ม) SUMMARIZE จะรักษา filter context ที่กระทบกับตารางนี้ไว้ตลอดการทำงาน | |
| groupBy_columnName | column | Optional | ไม่มีการจัดกลุ่ม (คืนค่าตารางเดิม) | คอลัมน์ที่ต้องการใช้เป็นเกณฑ์หลักในการจัดกลุ่มข้อมูล ต้องระบุเป็นชื่อคอลัมน์แบบครบถ้วนในรูปแบบ Table[Column] และต้องเป็นคอลัมน์ที่มีอยู่จริง ไม่สามารถใช้นิพจน์คำนวณแทนได้ ข้อดีเด่นของ SUMMARIZE คือสามารถอ้างถึงคอลัมน์จาก related table ได้โดยตรงโดยไม่ต้องใช้ฟังก์ชัน RELATED เมื่อระบุหลายคอลัมน์พร้อมกัน ผลลัพธ์จะเป็น distinct combinations ของคอลัมน์ทั้งหมด สามารถใช้ฟังก์ชัน ROLLUP ครอบคอลัมน์เพื่อสร้าง hierarchical subtotals |
| name | text | Optional | ไม่มีคอลัมน์คำนวณเพิ่มเติม | ⚠️ Deprecated Parameter – ชื่อของคอลัมน์คำนวณเพิ่มเติม (extension column) ที่ต้องการสร้างในตารางผลลัพธ์ ต้องระบุเป็นข้อความภายใน double quotes และต้องมี expression parameter คู่กัน Microsoft และ SQLBI แนะนำอย่างเป็นทางการว่า parameter นี้ไม่ควรใช้แล้วเนื่องจากมีปัญหาด้าน performance และความยากในการควบคุม filter context แนวทางที่ดีกว่าคือใช้ ADDCOLUMNS function ครอบ SUMMARIZE จากภายนอกแทน |
| expression | scalar | Optional | ไม่มีนิพจน์คำนวณ | ⚠️ Deprecated Parameter – นิพจน์คำนวณของ DAX ที่คืนค่า scalar value สำหรับคำนวณค่าสรุปของแต่ละกลุ่ม expression นี้จะถูก evaluate ภายใน filter context ที่ SUMMARIZE สร้างขึ้นสำหรับแต่ละกลุ่มโดยอัตโนมัติ ซึ่งอาจทำให้เกิดผลลัพธ์ที่ไม่คาดหวังในบางกรณี ต้องมี name parameter คู่กัน Microsoft และ SQLBI แนะนำให้ใช้รูปแบบ ADDCOLUMNS(SUMMARIZE(…), “name”, CALCULATE(expression)) แทนเพื่อควบคุม filter context ได้ชัดเจนและได้ performance ดีกว่า |
ใช้ SUMMARIZE สร้างตารางสรุปข้อมูลตามกลุ่มเพื่อเก็บไว้ใน VAR จากนั้นใช้ iterator functions (SUMX, AVERAGEX, COUNTX) คำนวณค่าสถิติต่างๆ จากกลุ่มข้อมูลนั้น เป็น use case หลักของ SUMMARIZE ในยุคปัจจุบัน
ใช้ SUMMARIZE(table, col1, col2, col3) เพื่อดึง unique combinations ของหลายคอลัมน์พร้อมกันที่มีอยู่จริงในข้อมูล คล้ายการทำ Remove Duplicates หลายคอลัมน์พร้อมกัน เนื่องจาก VALUES และ DISTINCT ใช้ได้เฉพาะคอลัมน์เดียว
SUMMARIZE สามารถอ้างถึงคอลัมน์จาก related table ได้โดยตรงโดยไม่ต้องใช้ RELATED เหมาะสำหรับจัดกลุ่มข้อมูลข้ามหลายตารางที่มี relationship กัน เช่น group Sales ตาม Products[Category] และ Customers[Region] พร้อมกัน
ใช้ ROLLUP function เพื่อสร้างตารางที่มี subtotal rows สำหรับแต่ละระดับของ hierarchy (เช่น ยอดรวมตามปี ตาม quarter และ grand total) พร้อมใช้ ISSUBTOTAL ระบุว่า row ไหนเป็น subtotal level ไหน เหมาะสำหรับ hierarchical report
// CALCULATED TABLE: สร้างตารางแสดง distinct categories Unique Categories = SUMMARIZE( Sales, Products[Category] ) // Context: // - Sales table มี relationship…// CALCULATED TABLE: สร้างตารางแสดง distinct categories
Unique Categories =
SUMMARIZE(
Sales,
Products[Category]
)
// Context:
// - Sales table มี relationship กับ Products table (many-to-one)
// - Products[Category] มีค่า: Electronics, Furniture, Clothing (ซ้ำหลาย row)
// - SUMMARIZE group ตาม Category และคืนค่าเฉพาะ distinct values
ตารางที่มี 1 คอลัมน์ (Category) และ 3 rows:
- Electronics
- Furniture
- Clothing
// CALCULATED TABLE: สร้างตารางแสดง Year-Category combinations ที่มีการขายจริง Year Category Pairs = SUMMARIZE( Sales, 'Date'[CalendarYear], Products[Category]…// CALCULATED TABLE: สร้างตารางแสดง Year-Category combinations ที่มีการขายจริง
Year Category Pairs =
SUMMARIZE(
Sales,
'Date'[CalendarYear],
Products[Category]
)
// Context:
// - Sales table มี relationship กับทั้ง Date และ Products tables
// - Date[CalendarYear]: 2022, 2023, 2024 (3 years)
// - Products[Category]: Electronics, Furniture, Clothing (3 categories)
// - Possible combinations: 3 × 3 = 9
// - แต่มีเพียง 7 combinations ที่มีการขายจริง
ตารางที่มี 2 คอลัมน์ (CalendarYear, Category) และ 7 rows:
- 2022, Electronics
- 2022, Furniture
- 2023, Electronics
- 2023, Furniture
- 2023, Clothing
- 2024, Electronics
- 2024, Clothing
(ไม่มี 2022-Clothing และ 2024-Furniture เพราะไม่มีการขาย)
// MEASURE: คำนวณยอดขายเฉลี่ยต่อลูกค้า 1 คน Average Sales Per Customer = VAR CustomerSales = ADDCOLUMNS( SUMMARIZE( Sales, Sales[CustomerID] ), "CustomerTotal",…// MEASURE: คำนวณยอดขายเฉลี่ยต่อลูกค้า 1 คน
Average Sales Per Customer =
VAR CustomerSales =
ADDCOLUMNS(
SUMMARIZE(
Sales,
Sales[CustomerID]
),
"CustomerTotal", CALCULATE(SUM(Sales[Amount]))
)
VAR AverageSales =
AVERAGEX(
CustomerSales,
[CustomerTotal]
)
RETURN
AverageSales
// Context:
// - Sales table มี CustomerID และ Amount columns
// - ปัจจุบัน filter context แสดงข้อมูล 50 customers
// - แต่ละคนซื้อหลาย transactions (รวมกว่า 200 rows)
ค่าเฉลี่ยยอดขายต่อลูกค้า 1 คน เช่น 12,450.00 บาท
(คำนวณจาก: รวมยอดขายของแต่ละคนก่อน จากนั้นหาค่าเฉลี่ยจาก 50 คน)
// MEASURE: หา Region-Category combination ที่มียอดขายสูงสุด Top Region Category Sales = VAR RegionCategorySales = ADDCOLUMNS( SUMMARIZE( Sales, Customers[Regio…// MEASURE: หา Region-Category combination ที่มียอดขายสูงสุด
Top Region Category Sales =
VAR RegionCategorySales =
ADDCOLUMNS(
SUMMARIZE(
Sales,
Customers[Region],
Products[Category]
),
"Total", CALCULATE(SUM(Sales[Amount]))
)
VAR TopCombination =
TOPN(
1,
RegionCategorySales,
[Total],
DESC
)
RETURN
SUMX(TopCombination, [Total])
// Context:
// - Sales ↔ Customers (มี Region column: North, South, East, West)
// - Sales ↔ Products (มี Category column: Electronics, Furniture, Clothing)
// - มี data covering 4 regions × 3 categories = 12 possible combinations
// - แต่มี actual data เพียง 10 combinations
ยอดขายสูงสุดของ Region-Category combination ใดๆ เช่น 2,850,000 บาท
(อาจเป็น North-Electronics หรือ South-Furniture ขึ้นอยู่กับข้อมูล)
// CALCULATED TABLE: สร้าง hierarchical report พร้อม subtotals Sales Hierarchy = ADDCOLUMNS( SUMMARIZE( Sales, ROLLUP( 'Date'[CalendarYear], Products[Category]…// CALCULATED TABLE: สร้าง hierarchical report พร้อม subtotals
Sales Hierarchy =
ADDCOLUMNS(
SUMMARIZE(
Sales,
ROLLUP(
'Date'[CalendarYear],
Products[Category]
)
),
"Total Sales", CALCULATE(SUM(Sales[Amount])),
"Transaction Count", CALCULATE(COUNTROWS(Sales)),
"Is Year Subtotal", ISSUBTOTAL('Date'[CalendarYear]),
"Is Grand Total",
ISSUBTOTAL('Date'[CalendarYear])
&& ISSUBTOTAL(Products[Category])
)
// Context:
// - Sales table with Date and Products relationships
// - 2 years (2023, 2024) × 3 categories (Electronics, Furniture, Clothing)
// - ROLLUP creates subtotals at each hierarchy level
ตารางที่มี 11 rows:
Detail rows (6):
- 2023, Electronics, 450000, 150, FALSE, FALSE
- 2023, Furniture, 320000, 110, FALSE, FALSE
- 2023, Clothing, 280000, 95, FALSE, FALSE
- 2024, Electronics, 580000, 175, FALSE, FALSE
- 2024, Furniture, 410000, 135, FALSE, FALSE
- 2024, Clothing, 350000, 120, FALSE, FALSE
Year subtotals (2):
- 2023, [blank], 1050000, 355, FALSE, FALSE
- 2024, [blank], 1340000, 430, FALSE, FALSE
Category subtotals (3):
- [blank], Electronics, 1030000, 325, TRUE, FALSE
- [blank], Furniture, 730000, 245, TRUE, FALSE
- [blank], Clothing, 630000, 215, TRUE, FALSE
Grand total (1):
- [blank], [blank], 2390000, 785, TRUE, TRUE
// ❌ SUMMARIZE - Deprecated pattern (ไม่แนะนำ) Sales by Category Wrong = SUMMARIZE( Sales, Products[Category], "Total", SUM(Sales[Amount]) // Performance issue!…=// ❌ SUMMARIZE - Deprecated pattern (ไม่แนะนำ)
Sales by Category Wrong =
SUMMARIZE(
Sales,
Products[Category],
"Total", SUM(Sales[Amount]) // Performance issue!
)
// ✅ SUMMARIZE + ADDCOLUMNS - Best for measures
Sales by Category in Measure =
VAR CategorySales =
ADDCOLUMNS(
SUMMARIZE(Sales, Products[Category]),
"Total", CALCULATE(SUM(Sales[Amount]))
)
RETURN
COUNTROWS(CategorySales) // นับจำนวน categories
// ✅ SUMMARIZECOLUMNS - Best for calculated tables
Sales by Category Table =
SUMMARIZECOLUMNS(
Products[Category],
'Date'[CalendarYear],
FILTER(
ALL('Date'[CalendarYear]),
'Date'[CalendarYear] >= 2023
),
"Total Sales", SUM(Sales[Amount]),
"Avg Sales", AVERAGE(Sales[Amount])
)
// Context:
// - SUMMARIZE works in all contexts but needs ADDCOLUMNS for best practice
// - SUMMARIZECOLUMNS has better performance but limited contexts
SUMMARIZE + ADDCOLUMNS (measure):
- Returns: 3 (จำนวน categories ที่มีการขาย)
- Works: ใน measure context ทุกประเภท
- Performance: ดี (ถ้าใช้ pattern ที่ถูกต้อง)
SUMMARIZECOLUMNS (table):
- Returns: ตารางที่มี Category, Year, Total Sales, Avg Sales
- Filter: เฉพาะปี 2023 ขึ้นไป
- Performance: ดีที่สุด ("very optimized query plan")
- Limitation: ใช้ไม่ได้ในบาง measure context
Microsoft และ SQLBI แนะนำอย่างเป็นทางการให้หลีกเลี่ยงการใช้พารามิเตอร์ name และ expression ใน SUMMARIZE เพื่อเพิ่มคอลัมน์คำนวณโดยตรง
.
มีเหตุผลสำคัญสามประการ: (1) Performance Issues – ฟังก์ชัน ADDCOLUMNS ให้ประสิทธิภาพที่ดีกว่าเพราะตัว DAX engine สามารถเพิ่มประสิทธิภาพ query plan ได้ดีกว่า (2) Filter Context Control – คอลัมน์คำนวณที่ถูกเพิ่มเข้าไปใน SUMMARIZE โดยตรงจะถูก evaluate ภายใน filter context ที่ SUMMARIZE สร้างขึ้นโดยอัตโนมัติ ซึ่งยากต่อการควบคุมและอาจให้ผลลัพธ์ที่ไม่คาดหวัง (3) Code Readability – การแยกส่วนของ grouping logic และ calculation logic ออกจากกันอย่างชัดเจนทำให้โค้ดอ่านง่ายและบำรุงรักษาได้สะดวกกว่า
.
ส่วนตัวผมแนะนำให้ใช้รูปแบบ ADDCOLUMNS(SUMMARIZE(table, columns), "name", CALCULATE(expression)) เสมอครับ 😎
SUMMARIZECOLUMNS เป็นฟังก์ชันรุ่นใหม่ที่ Microsoft ออกแบบมาเพื่อแก้ไขข้อจำกัดของ SUMMARIZE มี performance ดีกว่าอย่างมาก (“produces a very optimized query plan requiring just one storage engine query”) รองรับ filter arguments และ measure โดยตรง และมี syntax ที่ยืดหยุ่นกว่า
.
อย่างไรก็ตามมีข้อจำกัดสำคัญคือใช้ไม่ได้ในบาง measure context ที่มี complex context transition SUMMARIZE ยังคงจำเป็นสำหรับการสร้าง virtual table ใน measure เพื่อทำ intermediate calculations
.
แนวทางการเลือกใช้: (1) ใช้ SUMMARIZECOLUMNS สำหรับ calculated table หรือ DAX query ที่ต้องการ performance สูงสุด (2) ใช้ SUMMARIZE + ADDCOLUMNS สำหรับ measure ที่ต้องการ group data ก่อนนำไป iterate ด้วย SUMX, AVERAGEX เป็นต้น (3) ใช้ GROUPBY เมื่อต้องการใช้ CURRENTGROUP function
ความแตกต่างหลัก 3 ประการ: (1) จำนวนคอลัมน์ – VALUES และ DISTINCT ใช้ได้เฉพาะกับคอลัมน์เดียว ส่วน SUMMARIZE สามารถจัดกลุ่มหลายคอลัมน์พร้อมกันเพื่อหา distinct combinations (2) Blank Row – VALUES จะเพิ่ม blank row ถ้ามี filter ที่ทำให้เกิด blank (เช่น relationship ที่ไม่ match) ส่วน DISTINCT และ SUMMARIZE ไม่เพิ่ม blank row อัตโนมัติ (3) Related Tables – SUMMARIZE สามารถอ้างถึงคอลัมน์จาก related table ได้โดยตรงโดยไม่ต้องใช้ RELATED function ส่วน VALUES และ DISTINCT ต้องใช้กับคอลัมน์ที่อยู่ในตารางที่ระบุเท่านั้น
.
แนวทางการเลือกใช้: ถ้าต้องการ distinct values คอลัมน์เดียว ใช้ VALUES (หรือ DISTINCT ถ้าไม่ต้องการ blank row) ถ้าต้องการ multi-column combinations หรือ cross-table grouping ใช้ SUMMARIZE
ROLLUP function สร้าง subtotal rows ตาม hierarchy ที่กำหนดโดยอัตโนมัติ เช่น ROLLUP(Year, Quarter, Month) จะสร้าง: (1) Detail rows สำหรับทุก Year-Quarter-Month combination (2) Subtotal rows สำหรับแต่ละ Year-Quarter (3) Subtotal rows สำหรับแต่ละ Year (4) Grand total row ใช้คู่กับ ISSUBTOTAL function เพื่อระบุว่า row ไหนเป็น subtotal level ไหน
.
ข้อจำกัดสำคัญ 2 ประการ: (1) Data Lineage – ROLLUP ทำให้ SUMMARIZE ไม่ preserve data lineage ของคอลัมน์ที่ใช้ใน ROLLUP ซึ่งอาจทำให้เกิด error ถ้านำคอลัมน์เหล่านั้นไปใช้ใน filter context ภายหลัง (2) Performance – ROLLUP สร้าง rows เพิ่มเติมมากทำให้ช้าในกรณีที่มี hierarchy หลายระดับ
.
ส่วนตัวผม สำหรับ reporting ที่ซับซ้อน แนะนำให้ใช้ SUMMARIZECOLUMNS แทนครับ 😅
SUMMARIZE มี context behavior ที่สำคัญต้องเข้าใจ: (1) ใน Filter Context (เช่น measure) – SUMMARIZE รักษา filter context ที่กระทบกับตารางที่ระบุไว้ตลอดการทำงาน จะคืนค่าตารางที่มีเฉพาะข้อมูลที่ผ่าน filter เท่านั้น (2) ใน Row Context (เช่น calculated column) – SUMMARIZE ทำ context transition โดยอัตโนมัติ แปลง row context เป็น filter context สำหรับแต่ละ row (3) Extension Columns – ถ้าใช้ name/expression parameters (ไม่แนะนำ) expression จะถูก evaluate ใน filter context ที่ SUMMARIZE สร้างขึ้นสำหรับแต่ละกลุ่ม ซึ่งอาจให้ผลลัพธ์ที่ไม่คาดหวังถ้าไม่ระวัง
.
ที่เจ๋งคือนี่คือเหตุผลที่ต้องใช้ CALCULATE ครอบ expression ใน ADDCOLUMNS เพื่อควบคุม filter context ให้ชัดเจนครับ Best practice: ใช้ VAR เก็บ SUMMARIZE result ไว้ก่อน จากนั้นใช้ ADDCOLUMNS พร้อม CALCULATE เพื่อเพิ่มคอลัมน์คำนวณ รูปแบบนี้ควบคุม context ได้ชัดเจนและ debug ง่าย 💡
SUMMARIZE และ GROUPBY มีความคล้ายคลึงกันในการจัดกลุ่มข้อมูล แต่มีความแตกต่างสำคัญ: (1) Table Expansion – SUMMARIZE ขยาย relationship โดยอัตโนมัติและสามารถอ้างถึงคอลัมน์จาก related table ได้โดยตรง ส่วน GROUPBY ไม่ขยาย relationship (ต้องอยู่ในตารางเดียวกัน) (2) Aggregation Pattern – GROUPBY รองรับ aggregation โดยตรงภายในฟังก์ชัน และมีฟังก์ชัน CURRENTGROUP() สำหรับเข้าถึงข้อมูลในแต่ละกลุ่ม ส่วน SUMMARIZE ต้องใช้คู่กับ ADDCOLUMNS (3) Performance – GROUPBY มี performance ดีกว่าในบางกรณีเนื่องจากไม่ต้องขยาย relationship
.
แนวทางการเลือกใช้: ใช้ SUMMARIZE เมื่อต้องการ group ข้าม related tables หรือต้องการ syntax ที่ง่ายกว่า ใช้ GROUPBY เมื่อต้องการ performance สูงสุดในตารางเดียวหรือต้องการใช้ CURRENTGROUP function
SUMMARIZE ไม่รองรับใน DirectQuery mode เมื่อใช้ใน calculated columns หรือ Row-Level Security (RLS) rules ตามที่ Microsoft ระบุอย่างชัดเจน
.
อย่างไรก็ตาม SUMMARIZE สามารถใช้งานได้ใน DirectQuery mode เมื่ออยู่ใน measures และ calculated tables ข้อจำกัดนี้เกิดจากลักษณะการทำงานของ DirectQuery ที่ต้องแปลง DAX expression เป็น SQL query ซึ่ง SUMMARIZE ที่มี row context (เช่นใน calculated column) และ RLS rules ไม่สามารถแปลงได้อย่างมีประสิทธิภาพ
.
ถ้าต้องการใช้ grouping ใน DirectQuery mode สำหรับ calculated columns แนะนำให้ทำการ group ที่ source database แทนหรือใช้ Import mode สำหรับตารางที่มี calculated columns ที่ใช้ SUMMARIZE
SUMMARIZE ใช้สำหรับจัดกลุ่มข้อมูลและสร้างตารางสรุป คล้ายกับคำสั่ง GROUP BY ใน SQL หรือการทำ Pivot Table ใน Excel แต่มีความยืดหยุ่นมากกว่าเพราะเป็นฟังก์ชันที่สร้าง virtual table ได้ครับ
.
ที่เจ๋งคือมันสามารถอ้างถึงคอลัมน์จาก related table ได้โดยตรงโดยไม่ต้องใช้ RELATED เลย ทำให้ง่ายต่อการจัดกลุ่มข้อมูลข้ามหลายตาราง
.
ส่วนตัวผมใช้บ่อยมากเวลาต้องการสร้าง virtual table ภายใน measure แล้วนำไปคำนวณต่อด้วย SUMX หรือ AVERAGEX 😎
⚠️ ที่ต้องระวังคือ Microsoft แนะนำอย่างเป็นทางการว่าไม่ควรใส่คอลัมน์คำนวณเพิ่มเติมใน SUMMARIZE โดยตรงแล้วนะครับ ให้ใช้ ADDCOLUMNS ครอบจากภายนอกแทน จะได้ performance ดีกว่าและควบคุม filter context ได้ชัดเจนกว่า
.
สำหรับ calculated table แนะนำให้ใช้ SUMMARIZECOLUMNS แทน SUMMARIZE เพราะมี performance ดีกว่าอย่างมาก (“very optimized query plan”) เอาจริงๆ นะครับ วิธีนี้จะช่วยให้โค้ดทำงานได้เร็วขึ้นเยอะ 💡
Microsoft และ SQLBI แนะนำอย่างเป็นทางการ: “SUMMARIZE should not be used to add columns” แม้ว่า SUMMARIZE จะมี syntax ที่รองรับการเพิ่ม extension columns โดยใช้พารามิเตอร์ name และ expression เพื่อเพิ่มคอลัมน์คำนวณเพิ่มเติมได้ในคำสั่งเดียว แต่รูปแบบนี้ ไม่แนะนำให้ใช้แล้ว เนื่องจากมีปัญหาหลายประการ: (1) Performance Issues – มีประสิทธิภาพในการประมวลผลต่ำกว่าการใช้ ADDCOLUMNS ครอบ SUMMARIZE จากภายนอกอย่างมีนัยสำคัญ (2) Filter Context Control – expression ที่อยู่ภายใน extension columns จะถูก evaluate ใน filter context ที่ SUMMARIZE สร้างขึ้นโดยอัตโนมัติ ซึ่งยากต่อการควบคุมและอาจให้ผลลัพธ์ที่ไม่คาดหวัง (3) Code Readability – การแยกส่วนของ grouping logic และ calculation logic ออกจากกันทำให้โค้ดอ่านง่ายและบำรุงรักษาได้สะดวกกว่า แนวทางปฏิบัติที่ดีที่สุดคือ ADDCOLUMNS(SUMMARIZE(table, columns), “name”, CALCULATE(expression))
สำหรับกรณีที่ต้องการสร้าง calculated table หรือเขียน DAX query เพื่อดึงข้อมูลออกมาวิเคราะห์ Microsoft แนะนำอย่างยิ่งให้ใช้ฟังก์ชัน SUMMARIZECOLUMNS แทน SUMMARIZE เนื่องจาก SUMMARIZECOLUMNS เป็นฟังก์ชันรุ่นใหม่ที่ออกแบบมาเพื่อใช้งานลักษณะนี้โดยเฉพาะ มีประสิทธิภาพในการทำงานที่ดีกว่าอย่างเห็นได้ชัด (“produces a very optimized query plan”) สามารถระบุ filter arguments และ measure โดยตรงภายในฟังก์ชันเดียว และมี syntax ที่ยืดหยุ่นกว่า อย่างไรก็ตาม SUMMARIZECOLUMNS มีข้อจำกัดสำคัญคือใช้งานไม่ได้ในบาง measure context ที่มี complex row context transition ซึ่งในกรณีเหล่านี้ SUMMARIZE ยังคงเป็นเครื่องมือที่จำเป็น ด้วยเหตุนี้ นักวิเคราะห์ข้อมูลจึงต้องเรียนรู้ทั้งสองฟังก์ชันและเข้าใจว่าเมื่อไหร่ควรใช้อันไหน
✅ รูปแบบที่แนะนำ (Best Practice):
// ใช้ SUMMARIZE สำหรับ grouping เท่านั้น
// เพิ่มคอลัมน์คำนวณด้วย ADDCOLUMNS + CALCULATE จากภายนอก
Sales Per Customer =
VAR CustomerSummary =
ADDCOLUMNS(
SUMMARIZE(
Sales,
Sales[CustomerID]
),
"Total", CALCULATE(SUM(Sales[Amount]))
)
RETURN
AVERAGEX(CustomerSummary, [Total])
❌ รูปแบบที่ไม่แนะนำ (Deprecated):
// ไม่ควรใส่ extension columns ใน SUMMARIZE โดยตรง
Sales Per Customer =
VAR CustomerSummary =
SUMMARIZE(
Sales,
Sales[CustomerID],
"Total", SUM(Sales[Amount]) // Deprecated!
)
RETURN
AVERAGEX(CustomerSummary, [Total])
SUMMARIZE – เหมาะสมสำหรับใช้ภายใน measure เพื่อสร้าง virtual table สำหรับ intermediate calculations มีความสามารถพิเศษในการอ้างถึงคอลัมน์จาก related table โดยอัตโนมัติโดยไม่ต้องใช้ RELATED สามารถทำงานได้ทุก context ทั้ง calculated columns, calculated tables และ measures รองรับ ROLLUP สำหรับ hierarchical subtotals แต่มี performance ที่ต่ำกว่า modern alternatives และต้องใช้คู่กับ ADDCOLUMNS เพื่อ best practice
SUMMARIZECOLUMNS – ฟังก์ชันรุ่นใหม่ที่ Microsoft แนะนำอย่างเป็นทางการสำหรับ calculated table และ DAX query scenarios มี performance สูงสุด (“very optimized query plan”) สามารถระบุ filter arguments และเรียกใช้ measure โดยตรงภายในฟังก์ชันเดียวได้ มี syntax ที่ยืดหยุ่นและชัดเจนกว่า แต่มีข้อจำกัดสำคัญคือใช้งานไม่ได้ในบาง measure context ที่มี complex row context transition ไม่รองรับใน DirectQuery mode เช่นเดียวกับ SUMMARIZE
GROUPBY – ทางเลือกสำหรับ grouping ที่ไม่ต้องการให้ระบบขยาย relationship ของตารางโดยอัตโนมัติ มี performance ดีกว่า SUMMARIZE ในบางสถานการณ์ เหมาะสำหรับการคำนวณที่ต้องการวนซ้ำภายในแต่ละกลุ่มโดยใช้ฟังก์ชัน CURRENTGROUP เพื่อเข้าถึงข้อมูลในกลุ่มนั้นๆ มี syntax ที่ซับซ้อนกว่า SUMMARIZE แต่ให้การควบคุมที่ละเอียดกว่าในบางกรณี
การเข้าใจพฤติกรรม context ของ SUMMARIZE เป็นสิ่งสำคัญอย่างยิ่ง: (1) ใน Filter Context (เช่นใน measure) – SUMMARIZE รักษา filter context ที่กระทบกับตารางที่ระบุไว้ตลอดการทำงาน จะคืนค่าตารางที่มีเฉพาะข้อมูลที่ผ่าน filter context ปัจจุบันเท่านั้น (2) ใน Row Context (เช่นใน calculated column) – SUMMARIZE ทำ context transition โดยอัตโนมัติ แปลง row context เป็น filter context สำหรับแต่ละ row (3) Extension Columns (ไม่แนะนำ) – ถ้าใช้ name/expression parameters expression จะถูก evaluate ใน filter context ที่ SUMMARIZE สร้างขึ้นสำหรับแต่ละกลุ่ม ซึ่งอาจให้ผลลัพธ์ที่ไม่คาดหวังถ้าไม่ระวัง นี่คือเหตุผลที่ต้องใช้ CALCULATE ครอบ expression ใน ADDCOLUMNS เพื่อควบคุม filter context ให้ชัดเจน
การใช้งาน SUMMARIZE อย่างมีประสิทธิภาพต้องอาศัยความเข้าใจในหลักการสำคัญหลายประการ ประการแรกคือการจัดการกับ filter context ให้ถูกต้อง เมื่อใช้ SUMMARIZE ภายใน measure ควรใช้ VAR เก็บผลลัพธ์ของ SUMMARIZE ไว้ก่อนเพื่อให้สามารถตรวจสอบและ debug ได้ง่ายขึ้น จากนั้นใช้ ADDCOLUMNS เพิ่มคอลัมน์คำนวณโดยครอบนิพจน์ด้วย CALCULATE เสมอเพื่อให้ filter context ทำงานถูกต้อง ประการที่สองคือการเลือกใช้ฟังก์ชันที่เหมาะสมกับสถานการณ์ ถ้าต้องการสร้าง calculated table ให้ใช้ SUMMARIZECOLUMNS แทน SUMMARIZE เพราะจะได้ประสิทธิภาพที่ดีกว่ามาก แต่ถ้าต้องการสร้าง virtual table ภายใน measure ที่มี context ซับซ้อน SUMMARIZE จะเป็นตัวเลือกที่ดีกว่า ประการที่สามคือการหลีกเลี่ยงการใช้ extension columns ภายใน SUMMARIZE โดยตรง แม้ว่า syntax จะอนุญาตให้ทำได้ แต่วิธีนี้จะให้ผลลัพธ์ที่มีประสิทธิภาพต่ำกว่าและควบคุม context ได้ยากกว่ารูปแบบที่แนะนำ สุดท้ายคือการทดสอบและวัดประสิทธิภาพอยู่เสมอ โดยเฉพาะอย่างยิ่งเมื่อทำงานกับข้อมูลขนาดใหญ่หรือมีความสัมพันธ์ที่ซับซ้อน ควรใช้เครื่องมืออย่าง DAX Studio เพื่อวิเคราะห์ query plan และเวลาในการประมวลผลเพื่อให้มั่นใจว่าได้เลือกใช้ pattern ที่เหมาะสมที่สุดสำหรับสถานการณ์นั้นๆ