GROUPBY สร้างตารางสรุปโดยจัดกลุ่มตามคอลัมน์ที่กำหนด และเพิ่มคอลัมน์คำนวณแบบกลุ่มต่อกลุ่มได้ โดยใช้ CURRENTGROUP() เข้าถึงแถวภายในกลุ่ม เหมาะกับการคำนวณซ้อนหรือคำนวณจากคอลัมน์ชั่วคราว (local columns)
=GROUPBY(<Table>, [<GroupBy_ColumnName>], [<Name>], [<Expression>])
=GROUPBY(<Table>, [<GroupBy_ColumnName>], [<Name>], [<Expression>])
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
| Table | Table | Yes | ตารางต้นทางที่ต้องการจัดกลุ่ม (อาจเป็นตารางจาก model หรือตารางชั่วคราวจาก DAX ก็ได้) | |
| GroupBy_ColumnName | Column | Optional | ไม่มี | คอลัมน์ที่ใช้จัดกลุ่ม (สามารถระบุหลายคอลัมน์ได้ตามต้องการ) – ถ้าไม่ระบุเลยจะได้ตารางแถวเดียว |
| Name | String | Optional | ไม่มี | ชื่อคอลัมน์ใหม่ที่ต้องการเพิ่มเข้าตารางผลลัพธ์ (เป็น String ต้องใส่ใน “…”) |
| Expression | Expression | Optional | ไม่มี | นิพจน์ที่ใช้คำนวณค่าสำหรับคอลัมน์ใหม่ (ควรใช้ CURRENTGROUP() ร่วมกับ iterator เช่น SUMX, MAXX, COUNTROWS) |
เช่น ยอดรวมต่อ CustomerID หรือจำนวนแถวต่อกลุ่ม
เช่น MAXX/MINX/SUMX ภายในกลุ่มผ่าน CURRENTGROUP
Sales By Customer = GROUPBY( Sales, Sales[CustomerID], "Total Sales", SUMX(CURRENTGROUP(), Sales[Amount]) )Context: Sales มีคอลัมน์ CustomerID และ Amount
Sales By Customer =
GROUPBY(
Sales,
Sales[CustomerID],
"Total Sales", SUMX(CURRENTGROUP(), Sales[Amount])
)
ตารางที่มี CustomerID และ Total Sales (ยอดรวมต่อลูกค้า)
Transaction Count = GROUPBY( Sales, Sales[CustomerID], Sales[ProductID], "Transaction Count", COUNTROWS(CURRENTGROUP()) )Context: Sales มีคอลัมน์ CustomerID, ProductID
Transaction Count =
GROUPBY(
Sales,
Sales[CustomerID],
Sales[ProductID],
"Transaction Count", COUNTROWS(CURRENTGROUP())
)
ตารางแสดงจำนวนธุรกรรมแยกตาม CustomerID และ ProductID
Sales Summary = GROUPBY( Sales, Sales[CustomerID], "Total Sales", SUMX(CURRENTGROUP(), Sales[Amount]), "Avg Sales", AVERAGEX(CURRENTGROUP(), Sales[Amount]), "Ma…Context: Sales มีคอลัมน์ CustomerID, Amount
Sales Summary =
GROUPBY(
Sales,
Sales[CustomerID],
"Total Sales", SUMX(CURRENTGROUP(), Sales[Amount]),
"Avg Sales", AVERAGEX(CURRENTGROUP(), Sales[Amount]),
"Max Sales", MAXX(CURRENTGROUP(), Sales[Amount])
)
ตารางสรุปที่มีทั้งยอดรวม, ค่าเฉลี่ย, และค่าสูงสุดต่อลูกค้า
Max Avg Price By Category = VAR SubcategoryAvg = GROUPBY( Product, Product[Category], Product[Subcategory], "Avg Price", AVERAGEX(CURRENTGROUP(), Product[Price]…ถ้าใช้ SUMMARIZE จะทำไม่ได้ เพราะมันรวบรวม (aggregate) คอลัมน์ชั่วคราวไม่ได้ ต้องใช้ GROUPBY กับ CURRENTGROUP() เท่านั้น
Context: Product มีคอลัมน์ Category, Subcategory, Price
Max Avg Price By Category =
VAR SubcategoryAvg =
GROUPBY(
Product,
Product[Category],
Product[Subcategory],
"Avg Price", AVERAGEX(CURRENTGROUP(), Product[Price])
)
VAR MaxByCategory =
GROUPBY(
SubcategoryAvg,
[Category],
"Max Subcategory Avg", MAXX(CURRENTGROUP(), [Avg Price])
)
RETURN
MaxByCategory
ตารางแสดงค่าเฉลี่ยราคาสูงสุดของ Subcategory ในแต่ละ Category
Overall Stats = GROUPBY( Sales, "Total Amount", SUMX(CURRENTGROUP(), Sales[Amount]), "Row Count", COUNTROWS(CURRENTGROUP()) )Context: Sales มีคอลัมน์ Amount
Overall Stats =
GROUPBY(
Sales,
"Total Amount", SUMX(CURRENTGROUP(), Sales[Amount]),
"Row Count", COUNTROWS(CURRENTGROUP())
)
ตารางแถวเดียวที่มียอดรวมทั้งหมดและจำนวนแถวทั้งหมด
ต่างกันทั้งประสิทธิภาพและความสามารถ:
• SUMMARIZE ใช้เทคนิค “clustering” ที่ส่งคำสั่งไปทำที่ storage engine (VertiPaq) เลย จึงเร็วกว่าเมื่อจัดกลุ่มตามคอลัมน์ใน model แต่จัดการคอลัมน์ชั่วคราว (local columns) ได้ไม่ดี และอาจให้ผลลัพธ์ไม่ตรงความตั้งใจในบางกรณี
• GROUPBY ทำงานที่ formula engine หลังจาก materialize ตารางมาแล้ว ช้ากว่าเมื่อจัดกลุ่มตามคอลัมน์ใน model แต่จัดการคอลัมน์ชั่วคราวได้ดี และต้องใช้ CURRENTGROUP() เสมอ
หลักง่ายๆ: ใช้ SUMMARIZE กับคอลัมน์จริง, ใช้ GROUPBY กับคอลัมน์ชั่วคราว
เพราะ GROUPBY ถูกออกแบบมาให้ทำงานกับ CURRENTGROUP() โดยเฉพาะ ถ้าเขียน Expression โดยไม่ใช้ CURRENTGROUP() อาจได้ผลลัพธ์ไม่ตรงตามที่คาดหวัง หรือ error ในบาง DAX version เพราะ Microsoft เปลี่ยนพฤติกรรมของ GROUPBY ให้รองรับเฉพาะ CURRENTGROUP() เท่านั้น
CURRENTGROUP() คือ “ตัวแทน” ของแถวทั้งหมดในกลุ่มนั้นๆ ที่ iterator function (SUMX, MAXX, ฯลฯ) ต้องการใช้
ใช้ไม่ได้! เพราะ Expression ใน GROUPBY ทำงานแบบ row-by-row iteration โดยไม่มี context transition ที่ CALCULATE ต้องการ ถ้าพยายามใส่ CALCULATE จะได้ error หรือผลลัพธ์ผิดพลาด
ถ้าต้องการ context transition ให้ใช้ SUMMARIZE หรือ ADDCOLUMNS แทน
ใช้แบบผสม เพื่อให้ได้ทั้งประสิทธิภาพและความยืดหยุ่น:
1. ใช้ SUMMARIZE จัดกลุ่มชั้นในก่อน (จากตารางใน model) → เร็ว
2. ใช้ GROUPBY จัดกลุ่มชั้นนอก (จากตารางชั่วคราว) → คำนวณคอลัมน์ชั่วคราวได้
ตัวอย่าง:
VAR InnerGroup = SUMMARIZE(Sales, Sales[Category], Sales[Subcategory])
VAR OuterCalc = GROUPBY(InnerGroup, [Category], “Max”, MAXX(CURRENTGROUP(), …))
วิธีนี้หลีกเลี่ยงการ materialize ตารางใหญ่ด้วย GROUPBY ตั้งแต่แรก
GROUPBY ไม่ได้ใช้ VertiPaq storage engine เหมือน SUMMARIZE ทำให้ช้ากว่าเมื่อจัดกลุ่มตารางใหญ่ๆ จาก model เพราะต้อง materialize (โหลดข้อมูลมาเก็บในหน่วยความจำ formula engine) ทั้งหมด
ข้อแนะนำ:
• ใช้ GROUPBY กับตารางที่ผ่านการกรองหรือลดขนาดแล้ว (เล็กลง)
• ไม่ควรใช้ GROUPBY กับตาราง fact ขนาดใหญ่โดยตรง ให้ใช้ SUMMARIZE ลดขนาดก่อน
• เมื่อจำเป็นต้องใช้ GROUPBY ให้เก็บผลลัพธ์ไว้ใน VAR แล้วใช้ซ้ำ (ไม่ต้องคำนวณซ้ำ)
GROUPBY(