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 ดีกว่าอย่างมาก
| อาร์กิวเมนต์ | ชนิด | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
| table | table | ตารางข้อมูลที่ต้องการจัดกลุ่มและสรุป สามารถเป็นชื่อตารางโดยตรง หรือ table expression จากฟังก์ชันอื่นเช่น FILTER (กรองก่อนจัดกลุ่ม), ALL (ดึงข้อมูลทั้งหมดโดยไม่คำนึงถึง filter context), หรือ CALCULATETABLE (ปรับเปลี่ยน filter context ก่อนจัดกลุ่ม) SUMMARIZE จะรักษา filter context ที่กระทบกับตารางนี้ไว้ตลอดการทำงาน | |
| [groupBy_columnName]ไม่บังคับ | column | ไม่มีการจัดกลุ่ม (คืนค่าตารางเดิม) | คอลัมน์ที่ต้องการใช้เป็นเกณฑ์หลักในการจัดกลุ่มข้อมูล ต้องระบุเป็นชื่อคอลัมน์แบบครบถ้วนในรูปแบบ Table[Column] และต้องเป็นคอลัมน์ที่มีอยู่จริง ไม่สามารถใช้นิพจน์คำนวณแทนได้ ข้อดีเด่นของ SUMMARIZE คือสามารถอ้างถึงคอลัมน์จาก related table ได้โดยตรงโดยไม่ต้องใช้ฟังก์ชัน RELATED เมื่อระบุหลายคอลัมน์พร้อมกัน ผลลัพธ์จะเป็น distinct combinations ของคอลัมน์ทั้งหมด สามารถใช้ฟังก์ชัน ROLLUP ครอบคอลัมน์เพื่อสร้าง hierarchical subtotals |
| [name]ไม่บังคับ | text | ไม่มีคอลัมน์คำนวณเพิ่มเติม | ⚠️ Deprecated Parameter – ชื่อของคอลัมน์คำนวณเพิ่มเติม (extension column) ที่ต้องการสร้างในตารางผลลัพธ์ ต้องระบุเป็นข้อความภายใน double quotes และต้องมี expression parameter คู่กัน Microsoft และ SQLBI แนะนำอย่างเป็นทางการว่า parameter นี้ไม่ควรใช้แล้วเนื่องจากมีปัญหาด้าน performance และความยากในการควบคุม filter context แนวทางที่ดีกว่าคือใช้ ADDCOLUMNS function ครอบ SUMMARIZE จากภายนอกแทน |
| [expression]ไม่บังคับ | scalar | ไม่มีนิพจน์คำนวณ | ⚠️ Deprecated Parameter – นิพจน์คำนวณของ DAX ที่คืนค่า scalar value สำหรับคำนวณค่าสรุปของแต่ละกลุ่ม expression นี้จะถูก evaluate ภายใน filter context ที่ SUMMARIZE สร้างขึ้นสำหรับแต่ละกลุ่มโดยอัตโนมัติ ซึ่งอาจทำให้เกิดผลลัพธ์ที่ไม่คาดหวังในบางกรณี ต้องมี name parameter คู่กัน Microsoft และ SQLBI แนะนำให้ใช้รูปแบบ ADDCOLUMNS(SUMMARIZE(…), “name”, CALCULATE(expression)) แทนเพื่อควบคุม filter context ได้ชัดเจนและได้ performance ดีกว่า |
[ ] = อาร์กิวเมนต์ที่ไม่บังคับ
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 ที่เหมาะสมที่สุดสำหรับสถานการณ์นั้นๆ
ใช้ 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
SUMMARIZE จัดกลุ่มตาราง Sales ตามคอลัมน์ Category จาก related table (Products) โดยไม่ต้องใช้ RELATED function
ผลลัพธ์คือ distinct values ของ Category ทั้งหมด คล้ายกับใช้ VALUES(Products[Category]) หรือ DISTINCT(Products[Category]) แต่ SUMMARIZE มีข้อดีคือสามารถขยายเป็นหลายคอลัมน์ได้ในภายหลังและรองรับ related table columns โดยตรง
SUMMARIZE สร้างตารางที่มี distinct combinations ของ Year และ Category ที่มีอยู่จริงในข้อมูล Sales
ไม่ใช่ Cartesian product ทั้งหมด (9 combinations) แต่เป็นเฉพาะ combinations ที่มีการขายเกิดขึ้นจริงเท่านั้น (7 combinations) ส่วนตัวผมใช้แบบนี้บ่อยเวลาต้องการรู้ว่ามี Category ไหนขายใน Year ไหนบ้าง 💡
(ไม่มี 2022-Clothing และ 2024-Furniture เพราะไม่มีการขาย)
นี่คือ best practice pattern ที่ Microsoft และ SQLBI แนะนำอย่างเป็นทางการ
ขั้นตอนการทำงาน: (1) ใช้ SUMMARIZE group ตาราง Sales ตาม CustomerID ได้ virtual table ที่มี 50 rows (2) ใช้ ADDCOLUMNS เพิ่มคอลัมน์ CustomerTotal โดย wrap SUM ด้วย CALCULATE เพื่อสร้าง filter context ที่ถูกต้อง (3) ใช้ AVERAGEX iterate ผ่าน CustomerSales table และหาค่าเฉลี่ยของ CustomerTotal column
เอาจริงๆ รูปแบบนี้ให้ performance ดีที่สุดและควบคุม filter context ได้ชัดเจนครับ ⚠️ ห้ามใส่ extension column ใน SUMMARIZE โดยตรง 😅
(คำนวณจาก: รวมยอดขายของแต่ละคนก่อน จากนั้นหาค่าเฉลี่ยจาก 50 คน)
SUMMARIZE สร้าง virtual table ที่จัดกลุ่มตามทั้ง Region และ Category พร้อมกัน (multi-level grouping) ได้ 10 rows (เฉพาะ combinations ที่มีข้อมูล)
จากนั้น ADDCOLUMNS เพิ่มคอลัมน์ Total ที่คำนวณยอดขายของแต่ละกลุ่มโดยใช้ CALCULATE สร้าง filter context ที่ถูกต้อง TOPN เลือก row ที่มียอดขายสูงสุด 1 row ออกมา และ SUMX ดึงค่า Total จาก row นั้น ส่วนตัวผมใช้เทคนิคนี้บ่อยมากในการวิเคราะห์ข้อมูลหลายมิติครับ 😎
(อาจเป็น North-Electronics หรือ South-Furniture ขึ้นอยู่กับข้อมูล)
ROLLUP function สร้าง subtotal rows ตาม hierarchy ที่กำหนด (Year → Category) โดยอัตโนมัติ
ใช้ ADDCOLUMNS เพื่อเพิ่มคอลัมน์คำนวณ (Total Sales และ Transaction Count) รวมทั้งคอลัมน์ flag สำหรับระบุว่า row นั้นเป็น subtotal level ไหน โดยใช้ ISSUBTOTAL function ตรวจสอบ
ที่ต้องระวังคือ ROLLUP ทำให้ SUMMARIZE ไม่ preserve data lineage ซึ่งอาจทำให้เกิด error ถ้านำคอลัมน์จาก ROLLUP ไปใช้ใน filter context ภายหลังครับ 😅
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
ตัวอย่างนี้แสดงความแตกต่างและ use case ที่เหมาะสมของแต่ละฟังก์ชัน
(1) <strong>SUMMARIZE + ADDCOLUMNS</strong> เหมาะสำหรับสร้าง virtual table ใน measure เพื่อทำ intermediate calculations ทำงานได้ทุก context รองรับ row context transition และ complex filter context
(2) <strong>SUMMARIZECOLUMNS</strong> ออกแบบมาสำหรับ calculated table และ DAX query scenarios มี performance สูงสุดเนื่องจาก optimized query plan สามารถระบุ filter arguments และเรียกใช้ measure โดยตรง
เอาจริงๆ แนวทาง: ใช้ SUMMARIZECOLUMNS สำหรับ calculated table เพื่อ performance สูงสุด ใช้ SUMMARIZE + ADDCOLUMNS สำหรับ measure ที่ต้องการ virtual table 💡
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 จัดกลุ่มตามหมวด · ชี้ที่ชื่อใดชื่อหนึ่ง แล้วฟังก์ชันที่ใช้คู่กันจะมีจุดทอง
ADDCOLUMNS เป็นฟังก์ชัน table transformation ที่ใช้สำหรับเพิ่มคอลัมน์ใหม่ (Calculated Columns) เข้าไปในตารางที่มีอยู่เดิม โดยคำนวณค่าในแต่ละแถวผ่าน Row Context และส่งคืนตารางเดิมพร้อมคอลัมน์ใหม่ต่อท้าย
ADDMISSINGITEMS เติมสมาชิกที่หายไปในผลลัพธ์สรุปแบบกลุ่ม เพื่อให้แสดงครบทุกสมาชิกของคอลัมน์ที่ระบุ เหมาะกับรายงานที่ต้องการเห็นรายการที่ไม่มีข้อมูลด้วย
CROSSJOIN สร้างตารางใหม่โดยการรวมแถวทั้งหมดจากตารางที่ระบุ โดยสร้างทุก Combination ที่เป็นไปได้ ผลลัพธ์คือตารางที่มีจำนวนแถวเท่ากับผลคูณของจำนวนแถวของแต่ละตาราง
CURRENTGROUP คืนตารางย่อยของกลุ่มปัจจุบันและใช้ได้เฉพาะภายใน GROUPBY ช่วยให้คำนวณค่าที่อิงแถวภายในกลุ่มได้ เช่น SUMX/COUNTROWS/ MAXX ของกลุ่มนั้น
DETAILROWS คืนตารางแถวรายละเอียดของ measure ภายใต้บริบทปัจจุบัน เหมาะกับการดูรายละเอียด/ตรวจสอบการคำนวณของ measure
DISTINCT คืนค่าตารางที่มีคอลัมน์เดียว ซึ่งประกอบด้วยค่าที่ไม่ซ้ำกันจากคอลัมน์ที่ระบุ โดยไม่รวม Blank Row ที่เกิดจาก Invalid Relationship ความแตกต่างหลักจาก VALUES คือ DISTINCT จะซ่อน Data Quality Issues ในขณะที่ VALUES จะเตือนให้เห็น
EXCEPT คืนตารางของแถวที่อยู่ใน LeftTable แต่ไม่อยู่ใน RightTable เหมาะกับการหาสิ่งที่ขาดหาย เช่น สินค้าที่ไม่เคยขาย ลูกค้าที่ไม่มีธุรกรรม
GENERATE วนทีละแถวใน Table1 แล้วประเมิน Table2 ในบริบทของแถวนั้น (row context) จากนั้นรวมผลทั้งหมดเป็นตารางเดียว ถ้า Table2 ว่างเปล่าในรอบไหน แถวนั้นจาก Table1 จะถูกตัดออก (ต่างจาก GENERATEALL)
GENERATEALL วนแถวของตาราง 1 แล้วสร้าง Cartesian product กับผลลัพธ์ของตาราง 2 โดยคงแถวที่ไม่มีข้อมูลย่อย ต่างจาก GENERATE ตรงที่ไม่ตัดแถวหลักออก
GROUPBY สร้างตารางสรุปโดยจัดกลุ่มตามคอลัมน์ที่กำหนด และเพิ่มคอลัมน์คำนวณแบบกลุ่มต่อกลุ่มได้ โดยใช้ CURRENTGROUP() เข้าถึงแถวภายในกลุ่ม เหมาะกับการคำนวณซ้อนหรือคำนวณจากคอลัมน์ชั่วคราว (local columns)
IGNORE ใช้ภายใน SUMMARIZECOLUMNS เพื่อบอกว่า expression/measure นี้ต้องถูก “ละเว้น” ตอนตัดสินว่าแถวไหนเป็น non-blank ทำให้แถวในผลลัพธ์ไม่ถูกตัดทิ้งเพียงเพราะ measure ที่เลือกละเว้นเป็น BLANK
NATURALINNERJOIN ทำ inner join ระหว่าง LeftTable และ RightTable โดยใช้คอลัมน์ชื่อเดียวกันเป็นคีย์การจับคู่ คืนผลลัพธ์เฉพาะแถวที่จับคู่ได้ทั้งสองตาราง และมักใช้ร่วมกับ SELECTCOLUMNS เพื่อจัดชื่อคอลัมน์ให้ตรงกัน
ROLLUP บอก SUMMARIZE ให้สร้างแถว subtotal เพิ่มเติมตามคอลัมน์ที่กำหนด ทำให้ได้ทั้งรายละเอียดและรวมย่อยในผลลัพธ์เดียว
ROLLUPGROUP ระบุชุดคอลัมน์ที่จะถูกพิจารณาเป็น “กลุ่มเดียว” สำหรับการสร้าง subtotal/roll-up ช่วยลด subtotal บางระดับ และมักใช้ร่วมกับ ROLLUP ใน SUMMARIZE
สร้างตารางใหม่โดยเลือกเฉพาะคอลัมน์ที่ต้องการจากตารางต้นฉบับและเพิ่มคอลัมน์ที่คำนวณได้ ต่างจาก ADDCOLUMNS ตรงที่ SELECTCOLUMNS เริ่มจากตารางว่างแล้วเพิ่มเฉพาะคอลัมน์ที่ระบุ ทำให้สามารถปรับโครงสร้างตารางและเลือกข้อมูลที่จำเป็นได้อย่างยืดหยุ่น
คืนตารางที่เป็นผลแบบ semi-join ระหว่าง 2 ตาราง พร้อมแทนคอลัมน์ร่วมด้วยดัชนี 0-based ซึ่งคำนวณจากลำดับแถวของตารางอ้างอิงหลังจัดเรียง
SUMMARIZECOLUMNS เป็นฟังก์ชันหลักสำหรับสร้างตารางสรุปผล โดยจัดกลุ่มตามคอลัมน์ที่กำหนด พร้อมเพิ่มคอลัมน์คำนวณจากเมเชอร์ และสามารถใส่เงื่อนไขกรองได้ทันที
คืนตาราง Top N แถวจากตารางที่กำหนด โดยเรียงตามนิพจน์หนึ่งตัวหรือมากกว่า สามารถระบุทิศทางการเรียงลำดับแยกต่างหากสำหรับแต่ละเกณฑ์
COUNTROWS เป็นฟังก์ชันการรวม (Aggregation) ที่นับจำนวนแถวในตารางที่ระบุ ไม่ว่าจะเป็นตารางจริงในโมเดลหรือตารางเสมือน (Virtual Table) จากฟังก์ชันอื่นๆ เช่น FILTER, VALUES, DISTINCT นับเท่าไหร่? ผลลัพธ์ก็คือจำนวนแถวเต็ม ๆ
COUNTX ไล่ประเมินนิพจน์ทีละแถวในตาราง แล้วนับจำนวนแถวที่ได้ผลลัพธ์ไม่ว่าง เหมาะสำหรับการนับจากค่าที่คำนวณต่อแถว ไม่ใช่นับคอลัมน์ตรง ๆ
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
ALL มีพฤติกรรมแตกต่างกัน 2 แบบ: ใช้เป็น Table Expression จะคืนทุกแถวในตาราง หรือทุกค่าในคอลัมน์ โดยไม่สนใจ Filter ใดๆ เหมาะสำหรับใช้ร่วมกับ FILTER, COUNTROWS, SUMMARIZE หรือใช้เป็น CALCULATE Modifier เพื่อลบ Filter ออกจากตารางหรือคอลัมน์ที่ระบุ ทำให้สามารถคำนวณ Grand Total หรือหาเปอร์เซ็นต์เทียบกับยอดรวมได้
CALCULATETABLE evaluate table expression ภายใต้ filter context ที่ถูกปรับเปลี่ยน แล้วคืนค่าเป็น table (ตาราง) ซึ่งแตกต่างจาก CALCULATE ที่คืนค่าเป็น scalar value รองรับ filter arguments 3 รูปแบบ: Boolean expression, table expression, และ filter modifier functions (REMOVEFILTERS, ALL, KEEPFILTERS, USERELATIONSHIP, CROSSFILTER) มีพฤติกรรมเหมือน CALCULATE ในทุกแง่มุมของการจัดการ filter context รวมถึง context transition แต่เหมาะสำหรับการสร้าง intermediate table ที่ถูกกรองแล้วส่งต่อให้ iterator functions หรือใช้ใน calculated table มักมี performance ดีกว่า FILTER ใน simple filtering scenarios เพราะ DAX engine สามารถทำ cardinality estimation และ optimization ได้ดีกว่า
CONTAINSROW ตรวจสอบว่ามีแถวที่ค่าคอลัมน์ตรงกันหมดหรือไม่ ถ้าเจอจะคืนค่า TRUE ไม่มีจะคืน FALSE
TREATAS เป็นเสมือนการสร้าง "virtual relationship" โดยไม่ต้องแก้โมเดล ช่วยให้ส่งเงื่อนไขข้ามตารางที่ไม่เชื่อมกัน หรือเมื่อต้องการส่งหลายคีย์พร้อมกัน
UNION รวมหลายตารางให้เป็นตารางเดียวด้วยการต่อแถว โดยเก็บแถวซ้ำไว้ทั้งหมด เหมาะกับการรวมชุดข้อมูลที่มีโครงสร้างคอลัมน์สอดคล้องกัน
VALUES ดึงค่าที่ไม่ซ้ำจากคอลัมน์ หรือดึงแถวทั้งหมดจากตาราง โดยรวมแถว BLANK ที่เกิดจากข้อผิดพลาดของความสัมพันธ์ (Referential Integrity Violations) ส่วน DISTINCT จะไม่รวมแถว BLANK นี้
Comments
อีเมลของคุณจะไม่ถูกเผยแพร่