Thep Excel

ALLSELECTED – ลบตัวกรอง Visual แต่คง Slicer เพื่อสร้าง Visual Total

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[, ...]]])

By ThepExcel AI Agent
19 December 2025

Function Metrics


Popularity
7/10

Difficulty
6/10

Usefulness
8/10

Syntax & Arguments

=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

How it works

Visual Total – ยอดรวมของข้อมูลที่เลือก

คำนวณยอดรวมทั้งหมดของข้อมูลที่ผู้ใช้เลือกดูใน Visual โดยไม่สนใจการแบ่งกลุ่มภายใน Visual (row/column filters) แต่ยังเคารพ Slicer และ Page Filter ภายนอก ใช้ ALLSELECTED ร่วมกับ CALCULATE และ aggregation function เช่น SUM, AVERAGE

Percentage of Selected – เปอร์เซ็นต์เทียบกับยอดรวมที่เลือก

คำนวณสัดส่วนเปอร์เซ็นต์ของแต่ละ row เทียบกับยอดรวมของข้อมูลที่เลือกทั้งหมด ทำให้ยอดรวมเปอร์เซ็นต์ได้ 100% เสมอ ใช้ DIVIDE ร่วมกับ CALCULATE และ ALLSELECTED เพื่อคำนวณ denominator ที่เป็น Visual Total

Dynamic Benchmark – เส้น Reference ที่เปลี่ยนตาม Slicer

สร้างเส้น Benchmark, Target, หรือ Average Line ที่เปลี่ยนค่าตาม Slicer แต่คงที่ (constant) ตลอดแกน X ใน Chart ใช้ ALLSELECTED เพื่อลบ filter จากแกน X แต่คง filter จาก Slicer ไว้ เหมาะสำหรับ Line Chart และ Combo Chart

Ranking within Selection – จัดอันดับภายในข้อมูลที่เลือก

จัดอันดับข้อมูลภายในขอบเขตที่ผู้ใช้เลือก ไม่ใช่อันดับทั้งหมดของข้อมูล เช่น Top 10 ใน Region ที่เลือก หรือ Rank ของ Product ใน Category ที่เลือก ใช้ RANKX ร่วมกับ ALLSELECTED เพื่อกำหนดขอบเขตการจัดอันดับ

Examples

ตัวอย่างที่ 1: Visual Total พื้นฐาน – ยอดขายรวมที่เลือก
Visual Total = CALCULATE( SUM(Sales[Amount]), ALLSELECTED() ) // Data Model: // Sales table: Amount, Date, ProductID, RegionID // Related to Products[ProductID]…
ALLSELECTED() ลบ filter จาก Products[ProductName] และ Calendar[Quarter] ที่เกิดจาก Matrix Visual แต่ยังคง filter Year=2024 และ Region=Asia จาก Slicer ไว้ ทำให้ทุก cell แสดงยอดรวมเดียวกัน ส่วนตัวผมใช้ pattern นี้บ่อยมากเลยครับ เพราะมันช่วยให้เห็นภาพรวมของข้อมูลที่เลือกได้ชัดเจน 💡 ถ้าใช้ ALL(Sales) แทน จะได้ Grand Total ของทุกปีทุก Region (ไม่เคารพ Slicer) ถ้าใช้ SUM(Sales[Amount]) แบบปกติ จะได้ยอดขายของแต่ละ cell ตาม row/column context ไม่ใช่ Visual Total
DAX Formula:

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]

Result:

ทุก cell ใน Matrix แสดงค่าเดียวกัน = 2,500,000

ทุก Product ทุก Quarter: 2,500,000
(ยอดรวมทั้งหมดของ Asia 2024 ที่ผู้ใช้เลือก)

ถ้าเปลี่ยน Slicer เป็น Region = "Europe" ค่าจะเปลี่ยนเป็นยอดรวม Europe

ตัวอย่างที่ 2: Percentage of Selected – สัดส่วนที่เคารพ Slicer
% of Selected = VAR CurrentAmount = SUM(Sales[Amount]) VAR SelectedTotal = CALCULATE( SUM(Sales[Amount]), ALLSELECTED(Products[ProductName]) ) RETURN DIVIDE(Cur…
ALLSELECTED(Products[ProductName]) ลบ filter ProductName ที่เกิดจาก Matrix row context แต่คง Region=Asia และ Year=2024 จาก Slicer ไว้ ทำให้ SelectedTotal เป็นยอดรวมของ Product ทั้งหมดใน Asia 2024 (1,000,000) ไม่ใช่ Grand Total ทุก Region
.
ที่เจ๋งคือการใช้ VAR เก็บ SelectedTotal ทำให้คำนวณครั้งเดียวต่อ row (ไม่ซ้ำซ้อน) และป้องกัน shadow filter context ไม่ถูกต้อง
.
เปอร์เซ็นต์รวมได้ 100% เสมอเพราะ denominator เป็น Visual Total ส่วนตัวผมใช้ pattern นี้บ่อยมากสำหรับ dashboard นะครับ 😎
DAX Formula:

% 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]

Result:

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%

ตัวอย่างที่ 3: Dynamic Benchmark – Average Line ที่เปลี่ยนตาม Slicer
Average Selected = CALCULATE( AVERAGE(Sales[Amount]), ALLSELECTED(Calendar[Date]) ) // Data Model: // Sales related to Calendar by Date // Line Chart: X-axis =…
ALLSELECTED(Calendar[Date]) ลบ filter Date ที่เกิดจากแกน X ของ Chart ทำให้ได้ Average ของทุกวันในปี 2024 Category Electronics แต่คง filter Year=2024 และ Category=Electronics จาก Slicer ไว้
.
เส้นจึงคงที่ (ไม่ขึ้นลงตามวันที่) แต่เปลี่ยนค่าเมื่อเปลี่ยน Slicer ที่เจ๋งคือมันช่วยให้ user เห็น benchmark ได้ทันที 💡
.
ถ้าไม่ใช้ ALLSELECTED เส้น Average จะขึ้นลงตามยอดขายของแต่ละวัน ถ้าใช้ ALL(Calendar[Date]) จะได้ Average ทุกปีทุก Category (ไม่เคารพ Slicer)
DAX Formula:

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"

Result:

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

ตัวอย่างที่ 4: Ranking within Selection – อันดับใน Region ที่เลือก
Rank in Selected = RANKX( ALLSELECTED(Products[ProductName]), CALCULATE(SUM(Sales[Amount])), , DESC, DENSE ) // Data Model: // Sales related to Products and Reg…
RANKX iterate ทุก Product ที่อยู่ใน argument แรก ALLSELECTED(Products[ProductName]) คืน Product ทั้งหมดที่อยู่ใน Region=Asia (ตาม Slicer) แล้ว RANKX เปรียบเทียบยอดขายของแต่ละ Product กับ Product อื่นๆ ใน Asia เพื่อจัดอันดับ
.
ถ้าใช้ ALL(Products[ProductName]) จะได้อันดับทั่วโลก (ไม่เคารพ Slicer) การใช้ DENSE ทำให้ไม่มีการข้ามอันดับเมื่อมีค่าเท่ากัน ส่วนตัวผม pattern นี้ช่วยให้ user เห็น top performers ใน segment ที่สนใจได้ชัดเจนครับ 😎
DAX Formula:

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]

Result:

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

ตัวอย่างที่ 5: ALLSELECTED vs ALL – เปรียบเทียบผลลัพธ์
// Measure 1: Visual Total (ALLSELECTED) Selected Total = CALCULATE( SUM(Sales[Amount]), ALLSELECTED() ) // Measure 2: Grand Total (ALL) Grand Total = CALCULATE…
ALLSELECTED() เคารพ filter จาก Slicer (Year=2024, Region=Asia) จึงได้เฉพาะข้อมูลที่เลือก ส่วน ALL(Sales) ลบ filter ทั้งหมดรวมถึง Slicer จึงได้ Grand Total ของข้อมูลทั้งหมด
.
ความแตกต่างนี้สำคัญมาก: ALLSELECTED ให้ Visual Total (ตามที่ผู้ใช้เลือก) เหมาะสำหรับคำนวณเปอร์เซ็นต์ที่รวมได้ 100% ส่วน ALL ให้ Grand Total (ไม่เคารพ Slicer) เหมาะสำหรับดู contribution เทียบกับข้อมูลทั้งหมด
.
เอาจริงๆ นะครับ ต้องเข้าใจความแตกต่างนี้ให้ชัดเจนถึงจะใช้ ALLSELECTED อย่างมั่นใจได้ 💡
DAX Formula:

=// 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]

Result:

Selected Total: 2,500,000 (ยอดรวม Asia 2024)
Grand Total: 12,800,000 (ยอดรวมทุกปีทุก Region)

ผลต่าง: Grand Total มากกว่า Selected Total มาก
ทุก cell ใน Matrix แสดงค่าเดียวกันสำหรับแต่ละ measure

ตัวอย่างที่ 6: Expanded Table Caveat – ควบคุมด้วย Column Argument
// ❌ ไม่แนะนำ: Table argument Total All Dimensions = CALCULATE( SUM(Sales[Amount]), ALLSELECTED(Sales) ) // ลบ filter ของ Sales และ related table ทั้งหมด (Produ…
เมื่อใช้ ALLSELECTED(Sales) จะมี expanded table behavior – DAX จะลบ filter ของ Sales table และ related dimension table ทั้งหมด (Products, Regions, Calendar) เพราะ DAX expand fact table ให้รวม related column
.
การระบุ ALLSELECTED(Products[ProductName]) จะลบเฉพาะ filter ProductName แต่คง Regions และ Calendar filter ไว้ ทำให้ควบคุมผลลัพธ์ได้ชัดเจนและป้องกันการลบ filter ที่ไม่ต้องการ
.
ที่ต้องระวังคือ expanded table caveat นี้อาจให้ผลลัพธ์ที่ไม่คาดคิดได้ ส่วนตัวผมแนะนำให้ระบุ column เฉพาะเสมอนะครับ 😅
DAX Formula:

// ❌ ไม่แนะนำ: 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

Result:

Total All Dimensions: 5,000,000 (ลบ filter ทุก dimension)
Total Selected Products: 1,200,000 (ลบเฉพาะ Product filter)

ผลต่าง: การระบุ column ให้ผลลัพธ์ที่ควบคุมได้ชัดเจนกว่า
และป้องกันการลบ filter ที่ไม่ต้องการ

FAQs

ALLSELECTED ต่างจาก ALL และ REMOVEFILTERS อย่างไร?

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 คืออะไรและทำงานอย่างไร?

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 Functions?

เมื่อใช้ 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 ยากครับ 😎

Expanded Table Caveat คืออะไรและมีผลต่อ ALLSELECTED อย่างไร?

เมื่อใช้ 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?

ใช้ 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 ได้ไหม?

ใช่ 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 นะครับ 💡

ทำไม ALLSELECTED ถึงเป็นฟังก์ชันที่ซับซ้อนที่สุดใน DAX?

ตาม 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 หรือ ALLEXCEPT ในกรณีไหน?

ใช้ 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 ที่ต้องการเก็บบางมิติครับ 😎

Resources & Related

Additional Notes

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 ก็จะใช้งานได้อย่างมั่นใจ 😎

กลไกการทำงาน: 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 ที่ซ้อนกันหลายชั้น

เมื่อไหร่ควรใช้ ALLSELECTED

  • Visual Total – คำนวณยอดรวมของข้อมูลที่ผู้ใช้เลือกดูใน report โดยเคารพ Slicer
  • Percentage of Selected – คำนวณเปอร์เซ็นต์เทียบกับยอดรวมที่เลือก ทำให้ได้ผลรวม 100%
  • Dynamic Benchmark – สร้างเส้น average หรือ target line ที่เปลี่ยนตาม Slicer แต่คงที่ตลอดแกน X
  • Ranking within Selection – จัดอันดับภายในข้อมูลที่เลือก ไม่ใช่อันดับทั้งหมด
  • Time Intelligence แบบ Filtered – YTD หรือ Running Total ที่คำนวณจากช่วงเวลาใน Slicer เท่านั้น

ข้อควรระวังสำคัญ (Critical Warnings)

⚠️ อย่าใช้ภายใน 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]) เพื่อควบคุมผลลัพธ์ได้ชัดเจน

ALLSELECTED vs ALL vs REMOVEFILTERS

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

Performance และ DirectQuery Support

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 ที่ดีขึ้น

Leave a Reply

Your email address will not be published. Required fields are marked *