Thep Excel

GROUPBYจัดกลุ่มและคำนวณแบบละเอียด

GROUPBY สร้างตารางสรุปโดยจัดกลุ่มตามคอลัมน์ที่กำหนด และเพิ่มคอลัมน์คำนวณแบบกลุ่มต่อกลุ่มได้ โดยใช้ CURRENTGROUP() เข้าถึงแถวภายในกลุ่ม เหมาะกับการคำนวณซ้อนหรือคำนวณจากคอลัมน์ชั่วคราว (local columns)

fx
=GROUPBY(<Table>, [<GroupBy_ColumnName>], [<Name>], [<Expression>])

ความนิยม6/10
ความยาก6/10
ประโยชน์6/10

อัปเดต 13 December 2025

Syntax & Arguments

อาร์กิวเมนต์ ชนิด ค่าเริ่มต้น คำอธิบาย
Table Table ตารางต้นทางที่ต้องการจัดกลุ่ม (อาจเป็นตารางจาก model หรือตารางชั่วคราวจาก DAX ก็ได้)
[GroupBy_ColumnName]ไม่บังคับ Column ไม่มี คอลัมน์ที่ใช้จัดกลุ่ม (สามารถระบุหลายคอลัมน์ได้ตามต้องการ) – ถ้าไม่ระบุเลยจะได้ตารางแถวเดียว
[Name]ไม่บังคับ String ไม่มี ชื่อคอลัมน์ใหม่ที่ต้องการเพิ่มเข้าตารางผลลัพธ์ (เป็น String ต้องใส่ใน “…”)
[Expression]ไม่บังคับ Expression ไม่มี นิพจน์ที่ใช้คำนวณค่าสำหรับคอลัมน์ใหม่ (ควรใช้ CURRENTGROUP() ร่วมกับ iterator เช่น SUMX, MAXX, COUNTROWS)

[ ] = อาร์กิวเมนต์ที่ไม่บังคับ

Additional Notes

GROUPBY(

, , …, , , …)

GROUPBY เป็นฟังก์ชันตาราง (Table Function) ที่ใช้สร้างตารางสรุปโดยการจัดกลุ่มตามคอลัมน์ที่ระบุ และเพิ่มคอลัมน์คำนวณใหม่แบบกลุ่มต่อกลุ่มได้ ซึ่งใน Expression ต้องใช้ CURRENTGROUP() เป็นตัวอ้างอิงแถวภายในกลุ่ม เพื่อให้ iterator function เช่น SUMX, MAXX, AVERAGEX ทำงานกับแถวในกลุ่มนั้นๆ ได้

ที่เจ๋งของ GROUPBY คือ มันออกแบบมาให้จัดการกับ “คอลัมน์ชั่วคราว” (local columns) ที่สร้างขึ้นมาจากนิพจน์อื่นได้ดี เหมาะกับการทำ nested grouping หรือการคำนวณแบบซ้อนชั้น เช่น จัดกลุ่มย่อยก่อน คำนวณค่าเฉลี่ยในกลุ่มย่อย แล้วจัดกลุ่มใหญ่อีกทีเพื่อหาค่าสูงสุดของค่าเฉลี่ยเหล่านั้น

ส่วนตัวผมมองว่า GROUPBY กับ SUMMARIZE เป็นฟังก์ชันที่ผู้เขียน DAX มือใหม่มักสับสนกันบ่อยมาก แต่จริงๆ แล้วมีหลักง่ายๆ คือ:
• ใช้ SUMMARIZE เมื่อจัดกลุ่มตามคอลัมน์ใน model (คอลัมน์จริง) → เร็วกว่า เพราะใช้ VertiPaq storage engine
• ใช้ GROUPBY เมื่อจัดกลุ่มตามคอลัมน์ชั่วคราว (คำนวณมาจาก DAX) → ยืดหยุ่นกว่า แต่ช้ากว่าเพราะ materialize ข้อมูลใน formula engine

และข้อจำกัดสำคัญของ GROUPBY คือ ห้ามใช้ CALCULATE ภายใน Expression เพราะมัน iterate แบบ row-by-row โดยตรง ไม่มี context transition แบบที่ CALCULATE ต้องการ 😎

How it works

สรุปยอดหรือจำนวนต่อกลุ่ม

เช่น ยอดรวมต่อ CustomerID หรือจำนวนแถวต่อกลุ่ม

คำนวณค่าต่อกลุ่มด้วย iterator

เช่น MAXX/MINX/SUMX ภายในกลุ่มผ่าน CURRENTGROUP

Examples

ตัวอย่างที่ 1: จัดกลุ่มพื้นฐาน – ยอดรวมต่อลูกค้าSales By Customer = GROUPBY( Sales, Sales[CustomerID], "Total Sales", SUMX(CURRENTGROUP(), Sales[Amount]) )

GROUPBY จัดกลุ่มตาราง Sales ตาม CustomerID แล้วใช้ SUMX ร่วมกับ CURRENTGROUP() เพื่อรวมยอด Amount ของทุกแถวในกลุ่มนั้น โดย CURRENTGROUP() คืนค่าเป็นตารางย่อยของแถวในกลุ่ม

Context: Sales มีคอลัมน์ CustomerID และ Amount

fx
Sales By Customer =
GROUPBY(
Sales,
Sales[CustomerID],
"Total Sales", SUMX(CURRENTGROUP(), Sales[Amount])
)

ผลลัพธ์ตารางที่มี CustomerID และ Total Sales (ยอดรวมต่อลูกค้า)
ตัวอย่างที่ 2: จัดกลุ่มหลายคอลัมน์ – นับจำนวนธุรกรรมTransaction Count = GROUPBY( Sales, Sales[CustomerID], Sales[ProductID], "Transaction Count", COUNTROWS(CURRENTGROUP()) )

จัดกลุ่มตามสองคอลัมน์พร้อมกัน (CustomerID และ ProductID) แล้วใช้ COUNTROWS(CURRENTGROUP()) นับจำนวนแถวในแต่ละกลุ่ม ผลลัพธ์จะบอกว่าลูกค้าแต่ละคนซื้อสินค้าแต่ละชนิดกี่ครั้ง

Context: Sales มีคอลัมน์ CustomerID, ProductID

fx
Transaction Count =
GROUPBY(
Sales,
Sales[CustomerID],
Sales[ProductID],
"Transaction Count", COUNTROWS(CURRENTGROUP())
)

ผลลัพธ์ตารางแสดงจำนวนธุรกรรมแยกตาม CustomerID และ ProductID
ตัวอย่างที่ 3: หลายคอลัมน์คำนวณในครั้งเดียวSales Summary = GROUPBY( Sales, Sales[CustomerID], "Total Sales", SUMX(CURRENTGROUP(), Sales[Amount]), "Avg Sales", AVERAGEX(CURRENTGROUP(), Sales[Amount]), "Ma…

GROUPBY สามารถเพิ่มหลายคอลัมน์คำนวณในครั้งเดียวได้ โดยแต่ละคอลัมน์ใช้ CURRENTGROUP() อ้างอิงกลุ่มเดียวกัน ซึ่งประหยัดกว่าการเรียก GROUPBY หลายรอบ

Context: Sales มีคอลัมน์ CustomerID, Amount

fx
Sales Summary =
GROUPBY(
Sales,
Sales[CustomerID],
"Total Sales", SUMX(CURRENTGROUP(), Sales[Amount]),
"Avg Sales", AVERAGEX(CURRENTGROUP(), Sales[Amount]),
"Max Sales", MAXX(CURRENTGROUP(), Sales[Amount])
)

ผลลัพธ์ตารางสรุปที่มีทั้งยอดรวม, ค่าเฉลี่ย, และค่าสูงสุดต่อลูกค้า
ตัวอย่างที่ 4: Nested Grouping – คำนวณซ้อนชั้นMax Avg Price By Category = VAR SubcategoryAvg = GROUPBY( Product, Product[Category], Product[Subcategory], "Avg Price", AVERAGEX(CURRENTGROUP(), Product[Price]…

นี่คือกรณีที่ GROUPBY เหนือกว่า SUMMARIZE อย่างชัดเจน! เราจัดกลุ่มสองชั้น:
1. กลุ่มย่อยระดับ Category + Subcategory หาค่าเฉลี่ยราคา (สร้าง local column [Avg Price])
2. จัดกลุ่มใหญ่ระดับ Category หาค่าสูงสุดจาก [Avg Price] ที่คำนวณไว้

ถ้าใช้ SUMMARIZE จะทำไม่ได้ เพราะมันรวบรวม (aggregate) คอลัมน์ชั่วคราวไม่ได้ ต้องใช้ GROUPBY กับ CURRENTGROUP() เท่านั้น

Context: Product มีคอลัมน์ Category, Subcategory, Price

fx
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
ตัวอย่างที่ 5: จัดกลุ่มโดยไม่ระบุคอลัมน์ – คำนวณทั้งตารางOverall Stats = GROUPBY( Sales, "Total Amount", SUMX(CURRENTGROUP(), Sales[Amount]), "Row Count", COUNTROWS(CURRENTGROUP()) )

ถ้าไม่ระบุ GroupBy_ColumnName เลย GROUPBY จะคำนวณทั้งตาราง (ได้ตารางแถวเดียว) คล้ายการ aggregate ทั้งหมดโดยไม่แบ่งกลุ่ม ใช้ได้เมื่อต้องการคำนวณหลายค่าจากตารางพร้อมกัน

Context: Sales มีคอลัมน์ Amount

fx
Overall Stats =
GROUPBY(
Sales,
"Total Amount", SUMX(CURRENTGROUP(), Sales[Amount]),
"Row Count", COUNTROWS(CURRENTGROUP())
)

ผลลัพธ์ตารางแถวเดียวที่มียอดรวมทั้งหมดและจำนวนแถวทั้งหมด

FAQs

GROUPBY ต่างจาก SUMMARIZE อย่างไร?+

ต่างกันทั้งประสิทธิภาพและความสามารถ:
• SUMMARIZE ใช้เทคนิค "clustering" ที่ส่งคำสั่งไปทำที่ storage engine (VertiPaq) เลย จึงเร็วกว่าเมื่อจัดกลุ่มตามคอลัมน์ใน model แต่จัดการคอลัมน์ชั่วคราว (local columns) ได้ไม่ดี และอาจให้ผลลัพธ์ไม่ตรงความตั้งใจในบางกรณี
• GROUPBY ทำงานที่ formula engine หลังจาก materialize ตารางมาแล้ว ช้ากว่าเมื่อจัดกลุ่มตามคอลัมน์ใน model แต่จัดการคอลัมน์ชั่วคราวได้ดี และต้องใช้ CURRENTGROUP() เสมอ

หลักง่ายๆ: ใช้ SUMMARIZE กับคอลัมน์จริง, ใช้ GROUPBY กับคอลัมน์ชั่วคราว

ทำไมต้องใช้ CURRENTGROUP() เสมอใน Expression?+

เพราะ GROUPBY ถูกออกแบบมาให้ทำงานกับ CURRENTGROUP() โดยเฉพาะ ถ้าเขียน Expression โดยไม่ใช้ CURRENTGROUP() อาจได้ผลลัพธ์ไม่ตรงตามที่คาดหวัง หรือ error ในบาง DAX version เพราะ Microsoft เปลี่ยนพฤติกรรมของ GROUPBY ให้รองรับเฉพาะ CURRENTGROUP() เท่านั้น

CURRENTGROUP() คือ "ตัวแทน" ของแถวทั้งหมดในกลุ่มนั้นๆ ที่ iterator function (SUMX, MAXX, ฯลฯ) ต้องการใช้

GROUPBY ใช้ CALCULATE ได้ไหม?+

ใช้ไม่ได้! เพราะ Expression ใน GROUPBY ทำงานแบบ row-by-row iteration โดยไม่มี context transition ที่ CALCULATE ต้องการ ถ้าพยายามใส่ CALCULATE จะได้ error หรือผลลัพธ์ผิดพลาด

ถ้าต้องการ context transition ให้ใช้ SUMMARIZE หรือ ADDCOLUMNS แทน

Nested Grouping ควรใช้อะไร?+

ใช้แบบผสม เพื่อให้ได้ทั้งประสิทธิภาพและความยืดหยุ่น:
1. ใช้ SUMMARIZE จัดกลุ่มชั้นในก่อน (จากตารางใน model) → เร็ว
2. ใช้ GROUPBY จัดกลุ่มชั้นนอก (จากตารางชั่วคราว) → คำนวณคอลัมน์ชั่วคราวได้

ตัวอย่าง:
VAR InnerGroup = SUMMARIZE(Sales, Sales[Category], Sales[Subcategory])
VAR OuterCalc = GROUPBY(InnerGroup, [Category], "Max", MAXX(CURRENTGROUP(), …))

วิธีนี้หลีกเลี่ยงการ materialize ตารางใหญ่ด้วย GROUPBY ตั้งแต่แรก

ประสิทธิภาพของ GROUPBY เป็นอย่างไร?+

GROUPBY ไม่ได้ใช้ VertiPaq storage engine เหมือน SUMMARIZE ทำให้ช้ากว่าเมื่อจัดกลุ่มตารางใหญ่ๆ จาก model เพราะต้อง materialize (โหลดข้อมูลมาเก็บในหน่วยความจำ formula engine) ทั้งหมด

ข้อแนะนำ:
• ใช้ GROUPBY กับตารางที่ผ่านการกรองหรือลดขนาดแล้ว (เล็กลง)
• ไม่ควรใช้ GROUPBY กับตาราง fact ขนาดใหญ่โดยตรง ให้ใช้ SUMMARIZE ลดขนาดก่อน
• เมื่อจำเป็นต้องใช้ GROUPBY ให้เก็บผลลัพธ์ไว้ใน VAR แล้วใช้ซ้ำ (ไม่ต้องคำนวณซ้ำ)

Resources & Related

ฟังก์ชันที่ผู้เขียนโยงไว้กับ GROUPBY จัดกลุ่มตามหมวด · ชี้ที่ชื่อใดชื่อหนึ่ง แล้วฟังก์ชันที่ใช้คู่กันจะมีจุดทอง

ฟังก์ชันนี้GROUPBYTable manipulation
Table manipulation (5)
ADDCOLUMNS

ADDCOLUMNS เป็นฟังก์ชัน table transformation ที่ใช้สำหรับเพิ่มคอลัมน์ใหม่ (Calculated Columns) เข้าไปในตารางที่มีอยู่เดิม โดยคำนวณค่าในแต่ละแถวผ่าน Row Context และส่งคืนตารางเดิมพร้อมคอลัมน์ใหม่ต่อท้าย

CURRENTGROUP

CURRENTGROUP คืนตารางย่อยของกลุ่มปัจจุบันและใช้ได้เฉพาะภายใน GROUPBY ช่วยให้คำนวณค่าที่อิงแถวภายในกลุ่มได้ เช่น SUMX/COUNTROWS/ MAXX ของกลุ่มนั้น

SELECTCOLUMNS

สร้างตารางใหม่โดยเลือกเฉพาะคอลัมน์ที่ต้องการจากตารางต้นฉบับและเพิ่มคอลัมน์ที่คำนวณได้ ต่างจาก ADDCOLUMNS ตรงที่ SELECTCOLUMNS เริ่มจากตารางว่างแล้วเพิ่มเฉพาะคอลัมน์ที่ระบุ ทำให้สามารถปรับโครงสร้างตารางและเลือกข้อมูลที่จำเป็นได้อย่างยืดหยุ่น

SUMMARIZE

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 ดีกว่าอย่างมาก

SUMMARIZECOLUMNS

SUMMARIZECOLUMNS เป็นฟังก์ชันหลักสำหรับสร้างตารางสรุปผล โดยจัดกลุ่มตามคอลัมน์ที่กำหนด พร้อมเพิ่มคอลัมน์คำนวณจากเมเชอร์ และสามารถใส่เงื่อนไขกรองได้ทันที

Aggregation (1)
COUNTROWS

COUNTROWS เป็นฟังก์ชันการรวม (Aggregation) ที่นับจำนวนแถวในตารางที่ระบุ ไม่ว่าจะเป็นตารางจริงในโมเดลหรือตารางเสมือน (Virtual Table) จากฟังก์ชันอื่นๆ เช่น FILTER, VALUES, DISTINCT นับเท่าไหร่? ผลลัพธ์ก็คือจำนวนแถวเต็ม ๆ

Comments

อีเมลของคุณจะไม่ถูกเผยแพร่

CookieDurationDescription
cookielawinfo-checkbox-analytics11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checkbox-functional11 monthsThe cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checkbox-necessary11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-others11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-performance11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
viewed_cookie_policy11 monthsThe cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Functional
Performance
Analytics
Advertisement
Others