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 ด้วย

fx
=ALLSELECTED([table|column])

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

อัปเดต 19 December 2025

Syntax & Arguments

อาร์กิวเมนต์ ชนิด ค่าเริ่มต้น คำอธิบาย
[table|column]ไม่บังคับ table | column ทุกตารางและทุก column ใน filter context ปัจจุบัน ชื่อตารางหรือชื่อ column ที่ต้องการลบ filter context ถ้าระบุตารางจะลบ filter ของตารางนั้นและ related table ที่เชื่อมผ่าน relationship (expanded table behavior) ควรระมัดระวัง ถ้าระบุ column จะลบเฉพาะ filter ของ column นั้นๆ วิธีที่ปลอดภัยกว่า สามารถระบุหลาย column ได้โดยคั่นด้วยเครื่องหมายจุลภาค แต่ทุก column ต้องมาจากตารางเดียวกัน ต้องเป็นชื่อตารางหรือ column ที่มีอยู่จริงในโมเดล ไม่ใช่ expression

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

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

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

fx
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

ตัวอย่างที่ 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 นะครับ 😎

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

ตัวอย่างที่ 3: Dynamic Benchmark – Average Line ที่เปลี่ยนตาม SlicerAverage 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)

fx
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

ตัวอย่างที่ 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 ที่สนใจได้ชัดเจนครับ 😎

fx
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

ตัวอย่างที่ 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 อย่างมั่นใจได้ 💡

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

ตัวอย่างที่ 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 เฉพาะเสมอนะครับ 😅

fx
// ❌ ไม่แนะนำ: 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 ที่ไม่ต้องการ

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

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

ฟังก์ชันนี้ALLSELECTEDFilter
Filter (6)
ALL

ALL มีพฤติกรรมแตกต่างกัน 2 แบบ: ใช้เป็น Table Expression จะคืนทุกแถวในตาราง หรือทุกค่าในคอลัมน์ โดยไม่สนใจ Filter ใดๆ เหมาะสำหรับใช้ร่วมกับ FILTER, COUNTROWS, SUMMARIZE หรือใช้เป็น CALCULATE Modifier เพื่อลบ Filter ออกจากตารางหรือคอลัมน์ที่ระบุ ทำให้สามารถคำนวณ Grand Total หรือหาเปอร์เซ็นต์เทียบกับยอดรวมได้

ALLEXCEPT

ALLEXCEPT ใช้สำหรับ “ล้างตัวกรองเกือบทั้งหมด” โดยคงตัวกรองไว้เฉพาะคอลัมน์ที่ระบุ เหมาะกับการคำนวณ Sub-total/สัดส่วนภายในกลุ่ม เช่น ยอดขายต่อหมวดหมู่ โดยไม่สนตัวกรองอื่น ๆ แนวคิดหลักคือ ลบตัวกรองของตาราง แล้วคงตัวกรองของคอลัมน์ที่เลือกไว้

CALCULATE

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

CALCULATETABLE

CALCULATETABLE evaluate table expression ภายใต้ filter context ที่ถูกปรับเปลี่ยน แล้วคืนค่าเป็น table (ตาราง) ซึ่งแตกต่างจาก CALCULATE ที่คืนค่าเป็น scalar value รองรับ filter arguments 3 รูปแบบ: Boolean expression, table expression, และ filter modifier functions (REMOVEFILTERS, ALL, KEEPFILTERS, USERELATIONSHIP, CROSSFILTER) มีพฤติกรรมเหมือน CALCULATE ในทุกแง่มุมของการจัดการ filter context รวมถึง context transition แต่เหมาะสำหรับการสร้าง intermediate table ที่ถูกกรองแล้วส่งต่อให้ iterator functions หรือใช้ใน calculated table มักมี performance ดีกว่า FILTER ใน simple filtering scenarios เพราะ DAX engine สามารถทำ cardinality estimation และ optimization ได้ดีกว่า

FILTER

FILTER ใช้กรองแถวในตารางตามเงื่อนไขที่ซับซ้อน โดยวนลูปทุกแถวและประเมินเงื่อนไข เหมาะกับการกรองด้วย Measure หรือ Expression ซึ่ง Boolean Expression ทำไม่ได้ แต่ต้องระวังเรื่อง Performance เพราะเป็น Iterator Function ที่ช้ากว่า Boolean Expression ดังนั้นควรใช้เฉพาะเมื่อจำเป็น และอย่าใช้ FILTER กับ RELATED เพื่อกรองข้ามตาราง ให้กรองที่ Dimension Table โดยตรงแทน

REMOVEFILTERS

REMOVEFILTERS ลบ Filter ออกจากตารางหรือคอลัมน์ที่ระบุ ใช้ได้ใน CALCULATE เท่านั้น เทียบเท่า ALL เมื่อใช้เป็น CALCULATE Modifier แต่ชัดเจนและอ่านโค้ดง่ายกว่า แนะนำใช้แทน ALL เพราะสื่อความหมายได้ดีกว่า

Math and Trig (1)
DIVIDE

DIVIDE ทำการหารพร้อม Alternate Result หากตัวหารเป็นศูนย์หรือ BLANK ช่วยให้ Measure ไม่เกิด error และควบคุมค่าที่ต้องการแสดงได้

Time Intelligence (1)
LASTNONBLANKVALUE

LASTNONBLANKVALUE คืนค่าสุดท้ายที่ไม่เป็น BLANK ของ Expression เมื่อประเมินตามลำดับของ Column ในบริบทตัวกรองปัจจุบัน ใช้หา "ค่าล่าสุดที่มีข้อมูล" เช่นยอดขายของวันล่าสุดที่มีค่า

Table manipulation (1)
NONVISUAL

NONVISUAL ใช้ทำเครื่องหมายว่า filter expression นี้เป็น non-visual ซึ่งหมายความว่ามันจะส่งผลต่อการคำนวณ measure แต่จะไม่ไปทำให้แถวที่แสดงในตารางสรุปเปลี่ยนไป มักใช้ร่วมกับ SUMMARIZECOLUMNS เพื่อควบคุมพฤติกรรมของตัวกรองอย่างละเอียด

Statistical (1)
RANKX

RANKX เป็น iterator function ที่ iterate ทุกแถวใน table เพื่อประเมิน expression แล้วคืนอันดับของค่าใน current context เมื่อเทียบกับค่าทั้งหมด สามารถกำหนดทิศทางการเรียง (ASC/DESC) และวิธีจัดการอันดับเสมอ (Skip/Dense) ใช้บ่อยกับ ALL/ALLSELECTED เพื่อควบคุมชุดข้อมูลที่เปรียบเทียบ เหมาะสำหรับการจัดอันดับสินค้า ลูกค้า ภูมิภาค และ Top/Bottom analysis

Aggregation (1)
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

Comments

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