ALLSELECTED เป็น DAX function ที่ลบ filter context จาก Visual (row และ column filters) แต่คง filter context จาก Slicer, Page Filter และ Report Filter ไว้ ทำให้สามารถคำนวณ Visual Total ได้ ซึ่งเป็นยอดรวมของข้อมูลที่ผู้ใช้เลือกดูในปัจจุบัน ไม่ใช่ Grand Total ทั้งหมด ฟังก์ชันนี้ทำงานผ่าน Shadow Filter Context ซึ่งเป็น filter context ที่ DAX Engine เก็บไว้ก่อนที่ Visual จะเพิ่ม row/column filter เมื่อเรียก ALLSELECTED จะเรียกคืน shadow context นี้ ใช้ร่วมกับ CALCULATE และ SUM, AVERAGE, DIVIDE เพื่อคำนวณ Visual Total, Percentage of Selected, Dynamic Benchmark, Ranking within Selection และ Time Intelligence ที่เคารพ Slicer ต้องระวังการใช้งานใน iterator functions เช่น SUMX, FILTER เพราะอาจให้ผลลัพธ์ที่ไม่คาดคิด และระวัง Expanded Table Caveat ที่จะลบ filter ของ related table ด้วย
=ALLSELECTED([table|column[, table|column[, ...]]])
=ALLSELECTED([table|column[, table|column[, ...]]])
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
| table|column | table | column | Optional | ทุกตารางและทุก column ใน filter context ปัจจุบัน | ชื่อตารางหรือชื่อ column ที่ต้องการลบ filter context ถ้าระบุตารางจะลบ filter ของตารางนั้นและ related table ที่เชื่อมผ่าน relationship (expanded table behavior) ควรระมัดระวัง ถ้าระบุ column จะลบเฉพาะ filter ของ column นั้นๆ วิธีที่ปลอดภัยกว่า สามารถระบุหลาย column ได้โดยคั่นด้วยเครื่องหมายจุลภาค แต่ทุก column ต้องมาจากตารางเดียวกัน ต้องเป็นชื่อตารางหรือ column ที่มีอยู่จริงในโมเดล ไม่ใช่ expression |
คำนวณยอดรวมทั้งหมดของข้อมูลที่ผู้ใช้เลือกดูใน Visual โดยไม่สนใจการแบ่งกลุ่มภายใน Visual (row/column filters) แต่ยังเคารพ Slicer และ Page Filter ภายนอก ใช้ ALLSELECTED ร่วมกับ CALCULATE และ aggregation function เช่น SUM, AVERAGE
คำนวณสัดส่วนเปอร์เซ็นต์ของแต่ละ row เทียบกับยอดรวมของข้อมูลที่เลือกทั้งหมด ทำให้ยอดรวมเปอร์เซ็นต์ได้ 100% เสมอ ใช้ DIVIDE ร่วมกับ CALCULATE และ ALLSELECTED เพื่อคำนวณ denominator ที่เป็น Visual Total
สร้างเส้น Benchmark, Target, หรือ Average Line ที่เปลี่ยนค่าตาม Slicer แต่คงที่ (constant) ตลอดแกน X ใน Chart ใช้ ALLSELECTED เพื่อลบ filter จากแกน X แต่คง filter จาก Slicer ไว้ เหมาะสำหรับ Line Chart และ Combo Chart
จัดอันดับข้อมูลภายในขอบเขตที่ผู้ใช้เลือก ไม่ใช่อันดับทั้งหมดของข้อมูล เช่น Top 10 ใน Region ที่เลือก หรือ Rank ของ Product ใน Category ที่เลือก ใช้ RANKX ร่วมกับ ALLSELECTED เพื่อกำหนดขอบเขตการจัดอันดับ
Visual Total = CALCULATE( SUM(Sales[Amount]), ALLSELECTED() ) // Data Model: // Sales table: Amount, Date, ProductID, RegionID // Related to Products[ProductID]…Visual Total =
CALCULATE(
SUM(Sales[Amount]),
ALLSELECTED()
)
// Data Model:
// Sales table: Amount, Date, ProductID, RegionID
// Related to Products[ProductID] and Regions[RegionID]
// Slicer: Year = 2024, Regions[Region] = "Asia"
// Matrix Visual: Rows = Products[ProductName], Columns = Calendar[Quarter]
ทุก cell ใน Matrix แสดงค่าเดียวกัน = 2,500,000
ทุก Product ทุก Quarter: 2,500,000
(ยอดรวมทั้งหมดของ Asia 2024 ที่ผู้ใช้เลือก)
ถ้าเปลี่ยน Slicer เป็น Region = "Europe" ค่าจะเปลี่ยนเป็นยอดรวม Europe
% of Selected = VAR CurrentAmount = SUM(Sales[Amount]) VAR SelectedTotal = CALCULATE( SUM(Sales[Amount]), ALLSELECTED(Products[ProductName]) ) RETURN DIVIDE(Cur…% of Selected =
VAR CurrentAmount = SUM(Sales[Amount])
VAR SelectedTotal =
CALCULATE(
SUM(Sales[Amount]),
ALLSELECTED(Products[ProductName])
)
RETURN
DIVIDE(CurrentAmount, SelectedTotal, 0)
// Data Model:
// Sales related to Products by ProductID
// Slicer: Regions[Region] = "Asia", Calendar[Year] = 2024
// Matrix: Rows = Products[ProductName]
Product A: 35.0% (350,000 / 1,000,000)
Product B: 45.0% (450,000 / 1,000,000)
Product C: 20.0% (200,000 / 1,000,000)
-------------------------
รวม: 100.0%
เมื่อเปลี่ยน Slicer เปอร์เซ็นต์จะคำนวณใหม่แต่ยังรวมได้ 100%
Average Selected = CALCULATE( AVERAGE(Sales[Amount]), ALLSELECTED(Calendar[Date]) ) // Data Model: // Sales related to Calendar by Date // Line Chart: X-axis =…Average Selected =
CALCULATE(
AVERAGE(Sales[Amount]),
ALLSELECTED(Calendar[Date])
)
// Data Model:
// Sales related to Calendar by Date
// Line Chart: X-axis = Calendar[Date], Y-axis = Sales[Amount]
// Slicer: Calendar[Year] = 2024, Products[Category] = "Electronics"
Horizontal line ที่ระดับ 45,000 ตลอดแกน X
2024-01-01: 45,000
2024-01-02: 45,000
2024-12-31: 45,000
(Average ของยอดขาย Electronics ทั้งหมดในปี 2024)
เมื่อเปลี่ยน Slicer เป็น Year=2023 เส้นจะเปลี่ยนเป็น 42,000
Rank in Selected = RANKX( ALLSELECTED(Products[ProductName]), CALCULATE(SUM(Sales[Amount])), , DESC, DENSE ) // Data Model: // Sales related to Products and Reg…Rank in Selected =
RANKX(
ALLSELECTED(Products[ProductName]),
CALCULATE(SUM(Sales[Amount])),
,
DESC,
DENSE
)
// Data Model:
// Sales related to Products and Regions
// Slicer: Regions[Region] = "Asia"
// Table Visual: Products[ProductName], [Sales Amount], [Rank in Selected]
Product X: 850,000 | Rank 1 (สูงสุดใน Asia)
Product Y: 720,000 | Rank 2 (รองลงมาใน Asia)
Product Z: 580,000 | Rank 3
เมื่อเปลี่ยน Slicer เป็น Europe อันดับจะคำนวณใหม่ใน Europe
Product ที่ rank 1 ใน Asia อาจไม่ใช่ rank 1 ใน Europe
// Measure 1: Visual Total (ALLSELECTED) Selected Total = CALCULATE( SUM(Sales[Amount]), ALLSELECTED() ) // Measure 2: Grand Total (ALL) Grand Total = CALCULATE…=// Measure 1: Visual Total (ALLSELECTED)
Selected Total =
CALCULATE(
SUM(Sales[Amount]),
ALLSELECTED()
)
// Measure 2: Grand Total (ALL)
Grand Total =
CALCULATE(
SUM(Sales[Amount]),
ALL(Sales)
)
// Slicer: Calendar[Year] = 2024, Regions[Region] = "Asia"
// Matrix: Rows = Products[ProductName], Columns = Calendar[Quarter]
Selected Total: 2,500,000 (ยอดรวม Asia 2024)
Grand Total: 12,800,000 (ยอดรวมทุกปีทุก Region)
ผลต่าง: Grand Total มากกว่า Selected Total มาก
ทุก cell ใน Matrix แสดงค่าเดียวกันสำหรับแต่ละ measure
// ❌ ไม่แนะนำ: Table argument Total All Dimensions = CALCULATE( SUM(Sales[Amount]), ALLSELECTED(Sales) ) // ลบ filter ของ Sales และ related table ทั้งหมด (Produ…// ❌ ไม่แนะนำ: Table argument
Total All Dimensions =
CALCULATE(
SUM(Sales[Amount]),
ALLSELECTED(Sales)
)
// ลบ filter ของ Sales และ related table ทั้งหมด (Products, Regions, Calendar)
// ✅ แนะนำ: Column argument
Total Selected Products =
CALCULATE(
SUM(Sales[Amount]),
ALLSELECTED(Products[ProductName])
)
// ลบเฉพาะ filter ProductName แต่คง Regions และ Calendar filter
Total All Dimensions: 5,000,000 (ลบ filter ทุก dimension)
Total Selected Products: 1,200,000 (ลบเฉพาะ Product filter)
ผลต่าง: การระบุ column ให้ผลลัพธ์ที่ควบคุมได้ชัดเจนกว่า
และป้องกันการลบ filter ที่ไม่ต้องการ
ALL และ REMOVEFILTERS ลบ filter context ทั้งหมดรวมถึง Slicer, Page Filter และ Report Filter ทำให้ได้ Grand Total ของข้อมูลทั้งหมด
.
ส่วน ALLSELECTED ลบเฉพาะ filter ที่เกิดจากภายใน Visual (row context และ column context) แต่คง filter จากภายนอก Visual (Slicer, Page Filter, Report Filter) ไว้ ทำให้ได้ Visual Total ของข้อมูลที่ผู้ใช้เลือกดู
.
ใช้ ALL/REMOVEFILTERS เมื่อต้องการ Grand Total โดยไม่เคารพการเลือกของผู้ใช้ ใช้ ALLSELECTED เมื่อต้องการ Visual Total ที่เคารพการเลือกครับ 💡
Shadow Filter Context คือ filter context ที่ DAX Engine เก็บไว้ก่อนที่ Visual หรือ Iterator จะเพิ่ม row/column filter เมื่อ Visual สร้าง Matrix หรือ Table จะมีการเก็บ filter context เดิม (ที่มีเฉพาะ Slicer และ Page Filter) เป็น shadow context แล้วเพิ่ม row/column filter เข้าไปใน active filter context
.
เมื่อเรียก ALLSELECTED จะเรียกคืน shadow filter context นี้แทนที่จะใช้ active filter context ทำให้ได้ filter จากภายนอก Visual เท่านั้น กลไกนี้เป็นเหตุผลที่ ALLSELECTED ซับซ้อนมากเพราะขึ้นกับตำแหน่งที่ใช้และ filter context ที่ซ้อนกัน
.
เอาจริงๆ นะครับ ต้องเข้าใจ shadow context ให้ชัดเจนถึงจะใช้ ALLSELECTED อย่างมั่นใจได้ 😅
เมื่อใช้ ALLSELECTED ภายใน Iterator (SUMX, FILTER, ADDCOLUMNS) ผลลัพธ์อาจไม่ตรงความคาดหวังเพราะ ALLSELECTED จะคืน shadow filter context ของ iterator ชั้นในสุด ไม่ใช่ shadow context ของ Visual ภายนอก ทำให้ได้ผลลัพธ์ที่ผิดพลาดหรือซ้ำกันทุก row
.
ถ้าต้องใช้ใน iterator แนะนำให้เก็บผลลัพธ์ของ ALLSELECTED ไว้ใน VAR ก่อน iterate เพื่อให้ shadow filter context ถูกต้อง ไม่ควรเรียก measure ที่มี ALLSELECTED จาก measure อื่นหรือใช้ใน iterator โดยตรง
.
ส่วนตัวผมแนะนำให้ใช้ VAR เสมอเมื่อทำงานกับ ALLSELECTED นะครับ เพื่อป้องกันปัญหาที่ debug ยากครับ 😎
เมื่อใช้ ALLSELECTED(FactTable) เช่น ALLSELECTED(Sales) จะมีผลกับ dimension table ทุกตารางที่เชื่อมกับ Sales ผ่าน relationship ด้วย เพราะ DAX จะ expand fact table ให้รวม related column จาก dimension table ทำให้ filter จาก dimension table (เช่น Products, Regions, Calendar) ถูกลบด้วย
.
ถ้าต้องการควบคุมให้ชัดเจน แนะนำให้ระบุเป็น column เฉพาะ เช่น ALLSELECTED(Products[ProductName]) แทนที่จะใช้ ALLSELECTED(Sales) เพื่อป้องกันการลบ filter ที่ไม่ต้องการ การระบุ column จะลบเฉพาะ filter ของ column นั้นๆ
.
ที่ต้องระวังคือ caveat นี้อาจทำให้ได้ผลลัพธ์ที่ไม่คาดคิด ส่วนตัวผมแนะนำให้ระบุ column เฉพาะเสมอครับ 💡
ใช้ ALLSELECTED() แบบไม่มี argument เมื่อต้องการลบ filter ทุก column ที่อยู่ใน filter context ปัจจุบัน เหมาะกับกรณีที่ต้องการ Visual Total ทั้งหมดโดยไม่สนใจการแบ่งกลุ่มใดๆ แต่ยังคง filter จาก Slicer และ Page Filter ไว้
.
อย่างไรก็ตาม การระบุ argument ชัดเจน เช่น ALLSELECTED(Sales) หรือ ALLSELECTED(Products[ProductName]) จะปลอดภัยกว่าเพราะควบคุมได้ชัดเจนและหลีกเลี่ยง expanded table caveat การไม่ระบุ argument อาจลบ filter ที่ไม่ต้องการในกรณีที่มีหลาย Visual และ filter context ซับซ้อน
.
ส่วนตัวผมมักจะระบุ argument เสมอนะครับ เพื่อความชัดเจนและป้องกัน unexpected behavior ครับ 😅
ใช่ ALLSELECTED รองรับ DirectQuery Mode สำหรับ Measures และ Calculated Tables แต่ไม่รองรับสำหรับ Calculated Columns และ Row-Level Security (RLS) rules ใน DirectQuery Mode
.
ถ้าต้องการใช้ใน DirectQuery แนะนำให้ใช้ใน Measures เท่านั้นและทดสอบ performance เพราะอาจช้ากว่า Import Mode ขึ้นอยู่กับ query complexity และ data source Performance จะดีกว่าถ้าระบุ column เฉพาะแทนที่จะใช้ทั้งตารางเพื่อลด query ที่ส่งไป database
.
ส่วนตัวผมแนะนำให้ทดสอบ performance อย่างละเอียดเมื่อใช้ใน DirectQuery นะครับ 💡
ตาม SQLBI ALLSELECTED เป็นฟังก์ชันที่ซับซ้อนที่สุดใน DAX เพราะรวมพฤติกรรมที่ซับซ้อนหลายอย่าง: (1) Shadow Filter Context ซึ่งต้องเข้าใจว่า filter context ถูกเก็บและเรียกคืนอย่างไร (2) การทำงานแตกต่างใน Visual vs Iterator (3) Expanded Table Caveat ที่มีผลกับ related table (4) ผลลัพธ์ขึ้นอยู่กับตำแหน่งที่ใช้และ filter context ที่ซ้อนกัน
.
ทำให้ยากต่อการคาดเดาผลลัพธ์โดยไม่ทดสอบจริง นอกจากนี้การใช้งานผิดอาจให้ผลลัพธ์ที่ดูถูกต้องแต่จริงๆ ผิดและยากต่อการ debug
.
เอาจริงๆ นะครับ ต้องศึกษาและฝึกฝนอย่างดีถึงจะเชี่ยวชาญ ALLSELECTED ได้ครับ 😅
ใช้ ALLSELECTED เมื่อต้องการลบ filter ภายใน Visual แต่คง filter จาก Slicer และ Page Filter ไว้ เหมาะสำหรับ Visual Total, Percentage of Selected, Dynamic Benchmark
.
ใช้ ALLEXCEPT เมื่อต้องการลบ filter ทั้งหมดยกเว้น column ที่ระบุ โดยไม่สนใจว่า filter มาจาก Visual หรือ Slicer ตัวอย่าง: ALLEXCEPT(Sales, Regions[Region]) จะลบ filter ทุก column ใน Sales ยกเว้น Region ไม่ว่า Region filter มาจาก Slicer หรือ Visual
.
ALLSELECTED มี context awareness (แยก Visual vs Slicer) ส่วน ALLEXCEPT ไม่มี แนะนำให้ใช้ ALLSELECTED สำหรับ Visual Total และ ALLEXCEPT สำหรับ Grand Total ที่ต้องการเก็บบางมิติครับ 😎
ALLSELECTED เป็น DAX function ที่ใช้ลบ filter context จาก Visual (row และ column filters) แต่คง filter context จาก Slicer, Page Filter และ Report Filter ไว้ ฟังก์ชันนี้คืนค่า table expression ที่มี filter context เดียวกับสิ่งที่ผู้ใช้เลือกดูในปัจจุบัน
.
ที่เจ๋งคือ ALLSELECTED ทำให้คุณคำนวณ Visual Total ได้อย่างถูกต้อง ซึ่งเป็นยอดรวมของข้อมูลที่อยู่ใน Slicer แต่ไม่ถูกแบ่งตาม row/column ของ Visual
.
ส่วนตัวผม ALLSELECTED นี่ซับซ้อนมากนะครับ แต่ถ้าเข้าใจ Shadow Filter Context ก็จะใช้งานได้อย่างมั่นใจ 😎
ALLSELECTED ทำงานผ่านกลไกที่เรียกว่า Shadow Filter Context ซึ่งเป็น filter context ที่ DAX Engine เก็บไว้ก่อนที่ Visual จะเพิ่ม row และ column filter เมื่อ Power BI สร้าง Matrix หรือ Table Visual จะมีการเก็บ filter context เดิม (ที่มีเฉพาะ Slicer, Page Filter, Report Filter) ไว้เป็น shadow context แล้วเพิ่ม row/column filter จาก Visual เข้าไปในชั้น active filter context เมื่อเรียก ALLSELECTED() จะเรียกคืน shadow filter context นี้ ทำให้ได้ filter ที่มาจากภายนอก Visual เท่านั้น
กลไกนี้แตกต่างจาก ALL ซึ่งลบ filter context ทั้งหมดรวมถึง Slicer และแตกต่างจาก REMOVEFILTERS ที่มีพฤติกรรมเหมือน ALL ALLSELECTED เป็นฟังก์ชันที่ซับซ้อนที่สุดใน DAX ตามที่ SQLBI ระบุ เพราะผลลัพธ์ขึ้นอยู่กับตำแหน่งที่ใช้งานและ filter context ที่ซ้อนกันหลายชั้น
⚠️ อย่าใช้ภายใน Iterator Functions – การใช้ ALLSELECTED ใน SUMX, FILTER, ADDCOLUMNS อาจให้ผลลัพธ์ที่ไม่คาดคิด เพราะจะอ้างอิง shadow filter context ของ iterator ชั้นในสุด ไม่ใช่ shadow context ของ Visual ภายนอก ถ้าต้องใช้ควรเก็บผลลัพธ์ไว้ใน VAR ก่อน iterate
⚠️ ใช้เฉพาะใน Measure ที่วางตรงใน Visual – อย่าเรียก measure ที่มี ALLSELECTED จาก measure อื่น เพราะอาจทำให้ shadow filter context ไม่ถูกต้อง วางโดยตรงใน Visual หรือใช้ VAR เพื่อควบคุม evaluation order
⚠️ Expanded Table Caveat – ALLSELECTED(FactTable) จะลบ filter ของ dimension table ที่เชื่อมผ่าน relationship ด้วย แนะนำให้ระบุ column เฉพาะเจาะจง เช่น ALLSELECTED(Products[ProductName]) เพื่อควบคุมผลลัพธ์ได้ชัดเจน
| Function | ลบ Visual Filters | ลบ Slicer Filters | Use Case |
|---|---|---|---|
| ALLSELECTED | ✅ ใช่ | ❌ ไม่ | Visual Total (เคารพ Slicer) |
| ALL | ✅ ใช่ | ✅ ใช่ | Grand Total (ไม่เคารพ Slicer) |
| REMOVEFILTERS | ✅ ใช่ | ✅ ใช่ | เหมือน ALL (syntax ใหม่กว่า) |
ใช้ ALLSELECTED เมื่อต้องการ Visual Total ที่เคารพ Slicer | ใช้ ALL เมื่อต้องการ Grand Total ทั้งหมด | ใช้ ALLEXCEPT เมื่อต้องการลบ filter ทั้งหมดยกเว้นบาง column
ALLSELECTED รองรับ DirectQuery Mode สำหรับ Measures และ Calculated Tables แต่ไม่รองรับสำหรับ Calculated Columns และ Row-Level Security (RLS) rules ใน DirectQuery Mode Performance โดยทั่วไปดี แต่ควรหลีกเลี่ยงการใช้ใน iterator ซ้อนกันหลายชั้นเพราะอาจช้า
การใช้ ALLSELECTED ร่วมกับ CALCULATE เป็น pattern ที่แนะนำ เพราะ CALCULATE จะจัดการ filter context transition อย่างถูกต้อง ควรใช้ VAR เพื่อเก็บผลลัพธ์ของ ALLSELECTED ก่อนใช้ใน expression ซับซ้อนเพื่อป้องกัน shadow filter context ไม่ถูกต้องและเพื่อ performance ที่ดีขึ้น