AVERAGE คำนวณค่าเฉลี่ยเลขคณิตของตัวเลขทั้งหมดในคอลัมน์ โดยข้าม blank cells และข้อความ แต่นับค่า 0 เข้าในการคำนวณ ซึ่งทำให้ค่าเฉลี่ยอาจต่ำลงถ้ามีค่า 0 จำนวนมาก ทำงานภายใต้ filter context ปัจจุบันและทำ context transition ใน calculated column ทำให้สามารถอ้างอิงคอลัมน์จากตารางอื่นผ่าน relationship ได้
| อาร์กิวเมนต์ | ชนิด | คำอธิบาย |
|---|---|---|
| column | column | คอลัมน์ที่มีค่าตัวเลขที่ต้องการคำนวณค่าเฉลี่ย ต้องอ้างอิงในรูปแบบ Table[Column] และต้องมี data type เป็น Number, Currency, หรือ Decimal โดย AVERAGE จะนับเฉพาะค่าตัวเลข ข้าม blank และข้อความ แต่นับค่า 0 เข้าในการคำนวณ |
AVERAGE เป็น aggregation function ใน DAX ที่คำนวณค่าเฉลี่ยเลขคณิต (Arithmetic Mean) ของค่าตัวเลขทั้งหมดในคอลัมน์ โดยทำงานภายใต้ filter context ปัจจุบัน ฟังก์ชันนี้รับ parameter เพียง 1 ตัวคือการอ้างอิงคอลัมน์ในรูปแบบ Table[Column] และ return ค่าเป็น decimal number
การทำงานของ AVERAGE จะคำนวณผลรวมของตัวเลขทั้งหมดในคอลัมน์แล้วหารด้วยจำนวน row ที่มีค่าตัวเลข โดยมีพฤติกรรมพิเศษใน blank handling: blank cells จะถูกข้ามไปไม่นับในตัวหาร แต่ค่า 0 จะถูกนับเข้าในทั้งผลรวมและตัวหาร ทำให้ค่าเฉลี่ยอาจต่ำลงถ้ามีค่า 0 จำนวนมาก
ความแตกต่างระหว่าง AVERAGE กับ AVERAGEX คือ AVERAGE ใช้กับคอลัมน์ตัวเลขที่มีอยู่แล้ว ในขณะที่ AVERAGEX เป็น iterator function ที่ evaluate expression ต่อแต่ละ row ก่อนหาค่าเฉลี่ย เหมาะสำหรับการคำนวณที่ซับซ้อนเช่น Quantity × UnitPrice ที่ต้องคูณก่อนหาค่าเฉลี่ย ในทางเทคนิค AVERAGE ภายในจะเรียกใช้ AVERAGEX แต่ไม่มีผลต่อ performance
Filter Context: AVERAGE ทำงานภายใต้ filter context จาก slicer, visual, หรือ CALCULATE ดังนั้นผลลัพธ์จะเปลี่ยนไปตาม filter ที่ใช้งาน
Row Context: เมื่อเรียกใช้ใน calculated column AVERAGE จะทำ context transition โดยอัตโนมัติ แปลง row context ให้เป็น filter context ทำให้สามารถอ้างอิงคอลัมน์จากตารางอื่นผ่าน relationship ได้
ตัวอย่าง: คอลัมน์มีค่า [100, BLANK, 200, 0] → AVERAGE คำนวณ = (100 + 200 + 0) / 3 = 100 (ไม่ใช่ 300/4)
💡 Best Practice: ใช้ VAR…RETURN เมื่อต้องการเก็บค่าเฉลี่ยไว้ใช้ซ้ำใน measure ที่ซับซ้อน และใช้ DIVIDE แทนการหารด้วย / เพื่อป้องกัน division by zero error ถ้าต้องการคำนวณค่าเฉลี่ยจาก expression ให้ใช้ AVERAGEX แทน
คำนวณมูลค่าเฉลี่ยต่อ transaction เพื่อวิเคราะห์ขนาดของออเดอร์ เหมาะกับการดู customer behavior และ pricing strategy
คำนวณราคาเฉลี่ยของสินค้าในแต่ละ category โดยอาศัย filter context จาก visual หรือ slicer เหมาะกับ pricing comparison
วิเคราะห์ KPI เฉลี่ย (เช่น คะแนนความพึงพอใจ เวลาจัดส่ง) แยกตาม customer segment, region, หรือ product category
เปรียบเทียบค่าเฉลี่ยในบริบทปัจจุบันกับค่าเฉลี่ยรวมทั้งหมดโดยใช้ CALCULATE ร่วมกับ ALL
สมมติตาราง Sales มีคอลัมน์ Amount ที่เก็บมูลค่าการขายต่อธุรกรรม
ข้อมูลตัวอย่าง:
– Transaction 1: 1,000
– Transaction 2: 2,500
– Transaction 3: 3,800
– Transaction 4: 2,500
การคำนวณ:
AVERAGE = (1,000 + 2,500 + 3,800 + 2,500) / 4 = 9,800 / 4 = 2,450
💡 สังเกตว่า Measure นี้ทำงานภายใต้ filter context ปัจจุบัน ถ้ามี slicer กรอง Year = 2024 ค่าเฉลี่ยจะคำนวณเฉพาะธุรกรรมในปี 2024 เท่านั้นครับ ถ้าเพิ่ม Region = "Bangkok" ก็จะได้ค่าเฉลี่ยเฉพาะกรุงเทพฯ
Data Model Context:
– ตาราง Products มีคอลัมน์ Price และ Category
– Visual เป็น table ที่มี Products[Category] เป็นแถว
ข้อมูลตัวอย่าง Products:
| ProductID | Category | Price |
|———–|————-|——–|
| P001 | Electronics | 10,000 |
| P002 | Electronics | 15,000 |
| P003 | Clothing | 500 |
| P004 | Clothing | 800 |
| P005 | Clothing | 1,250 |
| P006 | Furniture | 7,000 |
| P007 | Furniture | 9,400 |
การคำนวณแต่ละ Category:
– Electronics: (10,000 + 15,000) / 2 = 12,500
– Clothing: (500 + 800 + 1,250) / 3 = 850
– Furniture: (7,000 + 9,400) / 2 = 8,200
💡 สังเกตว่า DAX สร้าง implicit filter ต่อแต่ละ row ใน visual ให้อัตโนมัติ ทำให้ AVERAGE คำนวณแยกตาม category โดยที่เราไม่ต้องเขียน CALCULATE เพิ่มเลย สะดวกมากครับ
Data Model Context:
– ตาราง Sales มีคอลัมน์ Amount และ Channel
– CALCULATE เปลี่ยน filter context โดยเพิ่ม filter condition
ข้อมูลตัวอย่าง Sales:
| TransactionID | Amount | Channel |
|—————|——–|———-|
| T001 | 2,000 | Online |
| T002 | 3,500 | Online |
| T003 | 4,250 | Online |
| T004 | 1,500 | Retail |
| T005 | 2,800 | Retail |
การทำงานของ CALCULATE:
1. Filter context เดิม: ทุก row ใน Sales
2. CALCULATE เพิ่ม filter: Sales[Channel] = "Online"
3. Filter context ใหม่: เฉพาะ T001, T002, T003
4. AVERAGE คำนวณ: (2,000 + 3,500 + 4,250) / 3 = 3,250
⚡ ข้อสังเกต: ไม่ว่า visual จะมี slicer กรอง Channel เป็นอะไร measure นี้จะ return ค่าเฉลี่ยเฉพาะ Online เสมอครับ เพราะ CALCULATE ทับ filter context ที่มีอยู่
Data Model Context:
– ตาราง Sales มีคอลัมน์ Amount และ Category
– ALL(Sales) ลบ filter context ทั้งหมดจากตาราง Sales
สมมติ Visual แสดง Category = Electronics:
Sales Data:
| TransactionID | Amount | Category |
|—————|——–|————-|
| T001 | 2,500 | Electronics |
| T002 | 3,250 | Electronics |
| T003 | 1,800 | Clothing |
| T004 | 2,200 | Clothing |
การคำนวณ:
1. CurrentAvg (เฉพาะ Electronics):
= (2,500 + 3,250) / 2 = 2,875
2. TotalAvg (ทุก Category):
= CALCULATE(AVERAGE(Sales[Amount]), ALL(Sales))
= (2,500 + 3,250 + 1,800 + 2,200) / 4
= 9,750 / 4 = 2,437.5
3. Difference:
= 2,875 – 2,437.5 = 437.5
4. Percentage:
= DIVIDE(437.5, 2,437.5, 0)
= 0.1795 (ประมาณ 18%)
💡 Context Behavior:
– CurrentAvg: ทำงานใน filter context ปัจจุบัน (Category = Electronics)
– TotalAvg: ALL(Sales) ลบ filter ทั้งหมด คำนวณค่าเฉลี่ยทุก row
– DIVIDE: ป้องกัน division by zero โดย return 0 ถ้า TotalAvg เป็น BLANK
เทคนิคนี้เหมาะมากสำหรับเปรียบเทียบ performance ของแต่ละ category กับค่าเฉลี่ยรวมครับ เอาไว้ทำ benchmark analysis
AVERAGE ใช้กับคอลัมน์ตัวเลขที่มีอยู่แล้วในตาราง รับ parameter เพียงตัวเดียวคือการอ้างอิง column เหมาะกับกรณีที่ข้อมูลที่ต้องการหาค่าเฉลี่ยเก็บอยู่ในคอลัมน์เดียว เช่น Sales[Amount]
AVERAGEX เป็น iterator function ที่วนลูปแต่ละ row ใน table แล้ว evaluate expression สำหรับแถวนั้นก่อนหาค่าเฉลี่ย เหมาะกับการคำนวณที่ต้องทำระดับ row เช่น Sales[Quantity] * Sales[UnitPrice] ที่ต้องคูณค่าสองคอลัมน์ก่อนหาค่าเฉลี่ย
ตัวอย่าง:
– AVERAGE(Sales[Amount]) → หาค่าเฉลี่ยของคอลัมน์ Amount ที่มีอยู่แล้ว
– AVERAGEX(Sales, Sales[Quantity] * Sales[UnitPrice]) → iterate แต่ละ row คูณ Quantity × UnitPrice แล้วหาค่าเฉลี่ย
💡 ในทางเทคนิค AVERAGE ภายในจะเรียกใช้ AVERAGEX อยู่แล้วครับ แต่ไม่มีผลต่อ performance เลือกใช้ตามความชัดเจนของโค้ด
AVERAGE มี blank handling behavior ที่แตกต่างกันระหว่าง BLANK กับ 0 ครับ
BLANK (ค่าว่าง): ข้ามไป ไม่นับในผลรวมและไม่นับในตัวหาร ดังนั้นไม่กระทบค่าเฉลี่ย
Zero (ค่า 0): ถูกนับเข้าในผลรวม (บวก 0) และนับใน row count ทำให้ค่าเฉลี่ยลดลง
Text/Logical: ถูกข้ามไป ไม่นับในการคำนวณ
ตัวอย่าง:
คอลัมน์มีค่า [100, BLANK, 200, 0]
– ผลรวม = 100 + 200 + 0 = 300
– จำนวน row ที่นับ = 3 (100, 200, 0 → ไม่นับ BLANK)
– ค่าเฉลี่ย = 300 / 3 = 100
ถ้านับ BLANK เป็น 0 จะได้ 300 / 4 = 75 (ผิดครับ)
No Rows Case: ถ้าไม่มี row ใดที่มีค่าตัวเลข AVERAGE จะ return BLANK (ไม่ใช่ 0 หรือ error)
💡 วิธีแทน BLANK ด้วย 0: ถ้าต้องการให้ BLANK กลายเป็น 0 ก่อนคำนวณ ใช้ AVERAGEX แบบนี้
AVERAGEX(Table, IF(ISBLANK(Table[Column]), 0, Table[Column]))
ความแตกต่างหลักเกิดจาก evaluation context ที่แตกต่างกันระหว่าง DAX และ Excel ครับ
1. Filter Context:
– DAX: AVERAGE ทำงานภายใต้ filter context จาก slicer, visual, หรือ CALCULATE ทำให้ผลลัพธ์เปลี่ยนแปลงตาม filter ที่ใช้งาน
– Excel: AVERAGE ใช้ cell range ที่กำหนดตายตัว เช่น =AVERAGE(A1:A10) ไม่เปลี่ยนตาม filter
2. Table Relationships:
– DAX: ใช้ relationship ระหว่างตารางทำให้ filter จากตารางหนึ่งส่งผลต่อการคำนวณในอีกตาราง (filter propagation)
– Excel: ไม่มี relationship ต้องใช้ VLOOKUP หรือ INDEX/MATCH เพื่อดึงข้อมูลจากตารางอื่น
3. Row Context vs Cell References:
– DAX: ใน calculated column มี row context ทำให้อ้างอิง column ในแถวเดียวกันได้โดยตรงเช่น Products[Price]
– Excel: ใช้ cell reference เช่น A2, B2 อ้างอิงตำแหน่งที่แน่นอน
💡 วิธีให้ได้ผลเหมือน Excel:
ใช้ ALL() เพื่อลบ filter context ทั้งหมด
Total Average = CALCULATE(AVERAGE(Sales[Amount]), ALL(Sales))
นี่จะคำนวณค่าเฉลี่ยทุก row เหมือน =AVERAGE($A$1:$A$100) ใน Excel ที่ไม่สนใจ filter
ทั้งสองวิธีให้ผลลัพธ์เหมือนกันในกรณีปกติ แต่มีข้อแตกต่างที่สำคัญครับ
ใช้ AVERAGE เมื่อ:
– ต้องการค่าเฉลี่ยของคอลัมน์ตัวเลขที่มีอยู่แล้ว (ไม่ต้องคำนวณ)
– โค้ดอ่านง่าย กระชับ และชัดเจน
– ไม่ต้องการ custom logic สำหรับ division by zero
ตัวอย่าง:
Avg Sales = AVERAGE(Sales[Amount])
ใช้ DIVIDE(SUM, COUNT) เมื่อ:
– ต้องการควบคุม division by zero behavior (ระบุค่า default ที่ return)
– ต้องการนับเฉพาะ row ที่ตรงเงื่อนไข (ใช้ COUNTROWS กับ FILTER)
– ต้องการความยืดหยุ่นในการคำนวณตัวหารหรือตัวตั้ง
ตัวอย่าง:
Avg Sales Safe =
DIVIDE(
SUM(Sales[Amount]),
COUNTROWS(Sales),
0 — Return 0 ถ้าไม่มี row (แทน BLANK)
)
ความแตกต่าง Division by Zero:
– AVERAGE: Return BLANK ถ้าไม่มี row ที่มีค่า
– DIVIDE: Return ค่า default ที่กำหนด (parameter ที่ 3) ถ้าตัวหารเป็น 0 หรือ BLANK
💡 Best Practice: ส่วนตัวผมแนะนำให้ใช้ AVERAGE สำหรับกรณีทั่วไป และใช้ DIVIDE(SUM, COUNT) เมื่อต้องการ error handling ที่แน่นอนหรือ custom logic ครับ
AVERAGE ใน Calculated Column:
– ทำงานใน row context (ประเมินทีละ row)
– ทำ context transition โดยอัตโนมัติ แปลง row context เป็น filter context
– สามารถอ้างอิง column ในตารางอื่นผ่าน relationship ได้
– คำนวณค่าและเก็บไว้ใน data model (เพิ่มขนาดไฟล์)
ตัวอย่าง Calculated Column:
Avg Category Price = AVERAGE(Products[Price])
// Context transition ทำให้คำนวณค่าเฉลี่ยทุก row ใน Products
// ทุกแถวได้ผลเหมือนกัน (ค่าเฉลี่ยทั้งตาราง)
AVERAGE ใน Measure:
– ทำงานใน filter context (ไม่มี row context)
– คำนวณ dynamic ตาม filter จาก visual, slicer, หรือ CALCULATE
– ไม่เก็บค่าใน data model ประหยัดพื้นที่
– Refresh ทุกครั้งที่ filter context เปลี่ยน
ตัวอย่าง Measure:
Avg Price = AVERAGE(Products[Price])
// คำนวณค่าเฉลี่ยตาม filter context ปัจจุบัน
// ใน visual ที่มี Category แต่ละ row ได้ค่าเฉลี่ยต่างกัน
💡 Best Practice:
– ใช้ Measure สำหรับ aggregation (SUM, AVERAGE, COUNT) → Dynamic, ประหยัดหน่วยความจำ
– ใช้ Calculated Column สำหรับ row-level calculation (Profit = Revenue – Cost) → Static, เก็บค่าไว้
Performance:
– Measure เร็วกว่าสำหรับ aggregation เพราะคำนวณแค่ค่าที่จำเป็น
– Calculated Column ช้าเพราะคำนวณทุก row และเก็บไว้ใน model
ส่วนตัวผมแนะนำให้ใช้ Measure สำหรับ AVERAGE เสมอครับ นอกจากจะมีเหตุผลพิเศษจริงๆ ที่ต้องเก็บค่าใน column
AVERAGE รองรับ DirectQuery แต่มีข้อจำกัดนะครับ
✅ รองรับใน:
– Measures (ทุกกรณี)
– Calculated tables ที่ไม่ใช้ unsupported function
– Visual calculations
❌ ไม่รองรับใน:
– Calculated columns
– Row-level security (RLS) rules
เหตุผล: DirectQuery query ข้อมูลจาก database แบบ real-time ไม่เก็บข้อมูลใน data model ทำให้ calculated column (ที่ต้องเก็บค่าทุก row) ใช้ไม่ได้
ทางเลือกสำหรับ DirectQuery:
1. ใช้ Measure แทน Calculated Column:
Measure คำนวณ dynamic ไม่ต้องเก็บค่า
2. คำนวณใน Database (View/Stored Procedure):
สร้าง view ใน SQL Server:
CREATE VIEW vw_SalesWithAvg AS
SELECT
*,
AVG(Amount) OVER (PARTITION BY Category) AS AvgCategoryAmount
FROM Sales
จากนั้น import view เข้า Power BI
3. ใช้ Import mode แทน DirectQuery:
ถ้าข้อมูลไม่ใหญ่มาก Import mode ให้ performance ดีกว่าและรองรับ feature ครบ
💡 Best Practice: ส่วนตัวผมแนะนำให้ใช้ AVERAGE ใน Measure สำหรับ DirectQuery และย้ายการคำนวณ complex ไปทำที่ database ผ่าน view หรือ stored procedure ครับ
ใน DAX: AVERAGE และ AVERAGEA ทำงานเหมือนกัน (ไม่มีความแตกต่าง)
ทั้งสองฟังก์ชันใช้ logic เดียวกันใน DAX:
– นับเฉพาะค่าตัวเลข
– ข้าม BLANK cells
– นับค่า 0 เข้าในการคำนวณ
– ข้าม text และ logical values
ความแตกต่างใน Excel:
ใน Excel AVERAGE และ AVERAGEA ต่างกันครับ
AVERAGE (Excel):
– นับเฉพาะตัวเลข
– ข้าม text, logical, blank
AVERAGEA (Excel):
– นับตัวเลข
– TRUE = 1, FALSE = 0
– Text และ empty = 0
ตัวอย่างใน Excel:
ข้อมูล: [10, 20, TRUE, FALSE, "text", blank]
=AVERAGE(…)
= (10 + 20) / 2 = 15
// นับแค่ 10, 20
=AVERAGEA(…)
= (10 + 20 + 1 + 0 + 0 + 0) / 6 = 5.17
// TRUE=1, FALSE=0, text=0, blank=0
แต่ใน DAX:
AVERAGE(Table[Column])
AVERAGEA(Table[Column])
// ทั้งคู่ให้ผลเหมือนกัน
💡 Best Practice: ใน DAX ส่วนตัวผมแนะนำให้ใช้ AVERAGE (ชัดเจนกว่า) เพราะ AVERAGEA ไม่มีประโยชน์เพิ่มเติมครับ ถ้าต้องการแปลง logical/text เป็นตัวเลขให้ใช้ AVERAGEX กับ custom expression
AVERAGEX(
Table,
IF(Table[Column] = TRUE, 1,
IF(Table[Column] = FALSE, 0,
Table[Column]
)
)
)
ฟังก์ชันที่ผู้เขียนโยงไว้กับ AVERAGE จัดกลุ่มตามหมวด · ชี้ที่ชื่อใดชื่อหนึ่ง แล้วฟังก์ชันที่ใช้คู่กันจะมีจุดทอง
AVERAGEA คืนค่าเฉลี่ยของค่าภายในคอลัมน์ และรวมการประมวลผลค่าตรรกะ/ข้อความตามกติกา (เช่น TRUE=1, FALSE=0, ข้อความ=0) เหมาะเมื่อข้อมูลมีชนิดปะปนและต้องการสะท้อนผลของค่าที่ไม่ใช่ตัวเลข
AVERAGEX เป็น Iterator Function ที่วนลูปตารางทีละแถว คำนวณ Expression แล้วนำผลลัพธ์มาหาค่าเฉลี่ย เหมาะสำหรับกรณีที่ต้องการเฉลี่ยค่าที่คำนวณได้ เช่น ราคา×จำนวน หรือค่าเฉลี่ยของ Measure ในแต่ละกลุ่ม
COUNT นับจำนวนแถวที่คอลัมน์มีค่าไม่ว่าง (non-blank) รองรับตัวเลข วันที่ และข้อความ แต่ไม่นับ Boolean ทำงานภายใต้ filter context และเกิด context transition เมื่อใช้ใน row context เหมาะสำหรับนับรายการที่มีข้อมูลในคอลัมน์เฉพาะ แต่ควรใช้ COUNTROWS แทนเมื่อนับแถวทั้งหมด
SUM รวมค่าตัวเลขทั้งหมดจากคอลัมน์เดียวภายใต้ filter context ปัจจุบัน ข้ามค่า BLANK และข้อความ แต่รวมค่า 0 หากต้องรวมจาก expression ให้ใช้ SUMX แทน
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
CALCULATE เป็นฟังก์ชันหลักที่สำคัญที่สุดใน DAX ใช้สำหรับ evaluate expression ภายใต้ filter context ที่ถูกปรับเปลี่ยน สามารถเพิ่มตัวกรองใหม่ ลบตัวกรองเดิม หรือแทนที่ filter ที่มีอยู่ได้ รองรับทั้ง Boolean expression และ table expression เป็น filter arguments พร้อม filter modifier functions เช่น REMOVEFILTERS, ALL, ALLEXCEPT, KEEPFILTERS เพื่อควบคุมการกรองอย่างละเอียด มีพฤติกรรมพิเศษคือ context transition ที่เปลี่ยน row context เป็น filter context โดยอัตโนมัติ ทำให้เป็นเครื่องมือหลักในการสร้าง measure ที่ซับซ้อนและ calculated column ที่ต้องใช้ aggregation
DIVIDE ทำการหารพร้อม Alternate Result หากตัวหารเป็นศูนย์หรือ BLANK ช่วยให้ Measure ไม่เกิด error และควบคุมค่าที่ต้องการแสดงได้
MOVINGAVERAGE คำนวณค่าเฉลี่ยเคลื่อนที่ (moving average) บนแกนของ Visual Calculations ในตารางข้อมูล เหมาะสำหรับทำเส้นแนวโน้มที่เรียบขึ้นและลดความผันผวนของข้อมูล
Comments
อีเมลของคุณจะไม่ถูกเผยแพร่