FILTER ใช้กรองแถวในตารางตามเงื่อนไขที่ซับซ้อน โดยวนลูปทุกแถวและประเมินเงื่อนไข เหมาะกับการกรองด้วย Measure หรือ Expression ซึ่ง Boolean Expression ทำไม่ได้ แต่ต้องระวังเรื่อง Performance เพราะเป็น Iterator Function ที่ช้ากว่า Boolean Expression ดังนั้นควรใช้เฉพาะเมื่อจำเป็น และอย่าใช้ FILTER กับ RELATED เพื่อกรองข้ามตาราง ให้กรองที่ Dimension Table โดยตรงแทน
| อาร์กิวเมนต์ | ชนิด | คำอธิบาย |
|---|---|---|
| table | table | ตารางหรือ Table Expression ที่ต้องการกรอง เช่น Sales, Products, ALL(Customers), VALUES(Products[Category]) |
| filter | boolean | เงื่อนไขที่ใช้กรอง ต้องคืนค่า TRUE หรือ FALSE สำหรับแต่ละแถว รองรับ Measure, Expression, และ RELATED() |
FILTER เป็นฟังก์ชันที่ใช้กรองแถวในตารางตามเงื่อนไขที่กำหนด โดยจะวนลูปทุกแถวแล้วประเมินเงื่อนไขทีละแถว (Row-by-row evaluation) แล้วคืนค่าเป็นตารางที่มีเฉพาะแถวที่ผ่านเงื่อนไข
.
ที่เจ๋งคือ FILTER สามารถใช้เงื่อนไขที่ซับซ้อนได้ เช่น กรองด้วย Measure หรือ Expression ที่คำนวณจากหลายคอลัมน์ ซึ่ง Boolean Expression ธรรมดาทำไม่ได้
.
แต่ที่ต้องระวังคือ FILTER เป็น Iterator Function ที่ประมวลผลทีละแถว ดังนั้นถ้าใช้กับตารางขนาดใหญ่อาจทำงานช้า Microsoft แนะนำให้ใช้ Boolean Expression แทนเสมอที่ทำได้ เพราะได้ Columnar Storage Optimization ทำให้เร็วกว่ามาก
.
ส่วนตัวผมใช้ FILTER เฉพาะเมื่อ “จำเป็น” จริงๆ เช่น กรองด้วย Measure ([Total Sales] > 50000) หรือ Virtual Column (Products[Price] * Products[Quantity] > 1000) ซึ่งเป็นค่าที่ไม่มีอยู่ใน Data Model 😎
Boolean Expression ใน CALCULATE ไม่รองรับกรณีเหล่านี้:
.
1. Measure – กรองด้วยค่าที่ต้องคำนวณ เช่น [Total Sales] > 50000
2. Virtual Column/Expression – กรองด้วยสูตรคำนวณ เช่น Products[Price] * Products[Quantity] > 1000
3. OR Condition – กรองด้วยหลายเงื่อนไขแบบ OR เช่น Products[Category] = “A” || Products[Category] = “B”
.
เรียกได้ว่า “ใช้ FILTER เมื่อกรองด้วยสิ่งที่ Boolean Expression ทำไม่ได้” 💡
กฎทองที่สำคัญที่สุดใน DAX คือ “กรองคอลัมน์ ไม่ใช่กรองตาราง” (Filter Columns, Not Tables)
.
❌ อย่าทำ: FILTER(Sales, RELATED(Products[Category]) = “Electronics”) – ช้ามาก และอาจให้ผลผิด!
✅ ให้ทำ: Products[Category] = “Electronics” – กรองที่ Dimension Table โดยตรง เร็วกว่า 100+ เท่า
.
เมื่อใช้ FILTER กับตาราง จะกรอง “expanded table” ที่รวม dimension ทุกตัว อาจทำให้ได้ผลลัพธ์ไม่ถูกต้อง ดังนั้น อย่าใช้ FILTER + RELATED เพื่อกรองข้ามตาราง ให้กรองที่ Dimension Table โดยตรงแทน!
ใช้ FILTER กรองด้วย Measure เช่น [Total Sales] > 50000 ซึ่งเป็นค่าที่คำนวณจาก SUM() ไม่ใช่คอลัมน์จริง Boolean Expression ทำไม่ได้
ใช้ FILTER กรองด้วย Expression ที่คำนวณจากหลายคอลัมน์ เช่น Products[Price] * Products[Quantity] > 1000 ซึ่งเป็นค่าที่ไม่มีอยู่ใน Data Model
ใช้ FILTER กรองด้วยหลายเงื่อนไขแบบ OR เช่น Products[Category] = "Electronics" || Products[Category] = "Appliances" ซึ่ง Boolean Expression เดี่ยวๆ ทำไม่ได้
เมื่อกรองด้วยคอลัมน์จริงที่มีอยู่ใน Data Model (Products[Color]) ควรใช้ Boolean Expression เพราะได้ Columnar Storage Optimization
Microsoft แนะนำให้ใช้ Boolean Expression เป็นอันดับแรกเสมอ แล้วค่อยใช้ FILTER เมื่อจำเป็นจริงๆ
ส่วนตัวผมจำง่ายๆ ว่า "ถ้าคอลัมน์มีอยู่จริง ใช้ Boolean Expression ได้เลย ไม่ต้องใช้ FILTER" 💡
กรณีนี้ "ต้อง" ใช้ FILTER เพราะเงื่อนไขคือ Measure ([Total Sales]) ซึ่งเป็นค่าที่คำนวณได้ ไม่ใช่คอลัมน์จริง
ถ้าลองใช้ Boolean Expression จะ ERROR: "A Boolean expression that is used as a table filter expression cannot reference a measure."
นี่คือกรณีที่ FILTER จำเป็นจริงๆ เพราะไม่มีทางเลือกอื่น เรียกได้ว่าเป็น "ข้อยกเว้น" ที่ต้องใช้ FILTER
Expression Sales[Quantity] * Sales[UnitPrice] เป็น "Virtual Column" ที่ไม่มีอยู่ใน Data Model ต้องคำนวณทีละแถว
ดังนั้น "ต้อง" ใช้ FILTER เพราะ Boolean Expression ทำไม่ได้ (ไม่สามารถใส่สูตรคำนวณใน Boolean Expression ได้)
ส่วนตัวผมถ้าใช้บ่อยจะสร้างเป็น Calculated Column ไว้เลย จะได้ไม่ต้องใช้ FILTER ทุกครั้ง ช่วยเรื่อง Performance ได้ 😎
นี่คือ Golden Rule ที่สำคัญที่สุด: "Filter Columns, Not Tables" – กรองคอลัมน์ ไม่ใช่กรองตาราง!
❌ วิธีผิด (FILTER + RELATED) มีปัญหา 2 อย่าง:
1. Performance แย่มาก – ต้องวนลูปทุกแถวใน Fact Table (หลักแสน/ล้านแถว)
2. อาจให้ผลผิด – FILTER กับตารางจะกรอง "expanded table" ที่รวม dimension ทุกตัว อาจทำให้ได้ผลลัพธ์ไม่ถูกต้อง
✅ วิธีถูก (Boolean Expression) เร็วกว่า 100+ เท่า เพราะ DAX Engine optimize ให้อัตโนมัติ
ผมเคยเห็นหลายคนใช้ FILTER + RELATED แบบผิดๆ นะครับ เพราะคิดว่าต้องกรองที่ Fact Table ทั้งที่จริงๆ แค่กรองที่ Dimension Table ก็พอ! 😎
ใช้ Boolean Expression เสมอที่ทำได้ เพราะได้ Columnar Storage Optimization ทำให้เร็วกว่า 100+ เท่า
ใช้ FILTER เฉพาะเมื่อ "จำเป็น" กรณีเหล่านี้:
1. กรองด้วย Measure – เช่น [Total Sales] > 50000 (ค่าที่ต้องคำนวณ)
2. กรองด้วย Virtual Column/Expression – เช่น Price * Quantity > 1000 (คอลัมน์เสมือน)
3. กรองหลายเงื่อนไขด้วย OR – เช่น Category = "A" || Category = "B"
⚠️ สำคัญ: อย่าใช้ FILTER + RELATED เพื่อกรองข้ามตาราง! ให้กรองที่ Dimension Table โดยตรงแทน เช่น Products[Category] = "Electronics" แทนที่จะใช้ FILTER(Sales, RELATED(Products[Category]) = "Electronics") 💡
จริงครับ เพราะ FILTER เป็น Iterator Function ที่วนลูปทีละแถวและประเมินเงื่อนไข
ถ้าใช้กับตารางขนาดใหญ่เช่น Fact Table หลักแสนแถว จะช้ามาก ส่วน Boolean Expression ได้ Columnar Storage Optimization ทำให้เร็วกว่า
ส่วนตัวผมแนะนำไม่ให้ใช้ FILTER กับ Fact Table โดยตรง ถ้าทำได้ให้ใช้กับ Dimension Table แทน (เช่น Products, Customers) ซึ่งมีแถวน้อยกว่า 😅
ใช่ครับ ภายในเครื่อง DAX จะแปลง Boolean Expression เป็น FILTER(ALL(Column), condition) อัตโนมัติ
แต่จะได้ Columnar Storage Optimization ทำให้เร็วมาก ส่วน FILTER ที่เขียนเอง จะไม่ได้ Optimization นี้ นี่คือเหตุผลที่ Boolean Expression เร็วกว่า FILTER มาก
ที่เจ๋งคือ DAX Engine ฉลาดพอที่จะ optimize ให้เราเอง แค่เราเขียนให้ถูกรูปแบบ 💡
ต้องระวังเรื่อง KEEPFILTERS ถ้าใช้ FILTER ใน CALCULATE โดยตรง มันจะ "เขียนทับ" Filter Context ที่มีอยู่เดิม (เช่น Filter จากผู้ใช้เลือกใน Slicer)
ถ้าต้องการ "รวม" Filter แทนการเขียนทับ ให้ใช้ KEEPFILTERS ห่อไว้:
CALCULATE(…, KEEPFILTERS(FILTER(…)))
นี่สำคัญมากในการทำ Dashboard ที่มี User Interaction ส่วนตัวผมใช้ KEEPFILTERS บ่อยมากครับ 😎
ทั้งคู่ใช้กรองตารางได้เหมือนกัน แต่ CALCULATETABLE จะแปลงเงื่อนไขเป็น FILTER หลายตัวแยกกันตามคอลัมน์ ซึ่งบางกรณีเร็วกว่า
เอาจริงๆ Microsoft แนะนำว่า "อย่าคิดว่า CALCULATETABLE ดีกว่า FILTER เสมอไป" เพราะ Performance ขึ้นอยู่กับ Cardinality และ Granularity ของข้อมูล
ส่วนตัวผมใช้ FILTER เมื่อต้องการ control logic เอง และใช้ CALCULATETABLE เมื่อมีหลายเงื่อนไขที่เป็นอิสระต่อกัน
ฟังก์ชันที่ผู้เขียนโยงไว้กับ FILTER จัดกลุ่มตามหมวด · ชี้ที่ชื่อใดชื่อหนึ่ง แล้วฟังก์ชันที่ใช้คู่กันจะมีจุดทอง
ALL มีพฤติกรรมแตกต่างกัน 2 แบบ: ใช้เป็น Table Expression จะคืนทุกแถวในตาราง หรือทุกค่าในคอลัมน์ โดยไม่สนใจ Filter ใดๆ เหมาะสำหรับใช้ร่วมกับ FILTER, COUNTROWS, SUMMARIZE หรือใช้เป็น CALCULATE Modifier เพื่อลบ Filter ออกจากตารางหรือคอลัมน์ที่ระบุ ทำให้สามารถคำนวณ Grand Total หรือหาเปอร์เซ็นต์เทียบกับยอดรวมได้
ALLCROSSFILTERED ใช้ล้างตัวกรองทั้งหมดออกจากตารางที่ระบุ รวมถึงตัวกรองที่ส่งผ่านมาจากตารางอื่น (Cross-filter) ใช้ได้เฉพาะเป็น Modifier ใน CALCULATE/CALCULATETABLE เท่านั้น ไม่สามารถคืนค่าเป็นตารางได้
ALLEXCEPT ใช้สำหรับ “ล้างตัวกรองเกือบทั้งหมด” โดยคงตัวกรองไว้เฉพาะคอลัมน์ที่ระบุ เหมาะกับการคำนวณ Sub-total/สัดส่วนภายในกลุ่ม เช่น ยอดขายต่อหมวดหมู่ โดยไม่สนตัวกรองอื่น ๆ แนวคิดหลักคือ ลบตัวกรองของตาราง แล้วคงตัวกรองของคอลัมน์ที่เลือกไว้
ALLNOBLANKROW ทำงานคล้าย ALL แต่มีจุดเด่นคือ “ตัดแถวว่าง” ที่ระบบสร้างขึ้นอัตโนมัติเมื่อข้อมูลหลุดความสัมพันธ์ เช่น คีย์ในตารางข้อเท็จจริงไม่พบในตารางมิติ จึงเหมาะกับการคำนวณยอดรวม/สัดส่วนที่ไม่ต้องการให้แถวว่างเข้ามาปนผลลัพธ์ และยังใช้เป็นตัวช่วยตรวจจับปัญหาคุณภาพข้อมูลในโมเดลได้ด้วย
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 ด้วย
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 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 ได้ดีกว่า
ADDCOLUMNS เป็นฟังก์ชัน table transformation ที่ใช้สำหรับเพิ่มคอลัมน์ใหม่ (Calculated Columns) เข้าไปในตารางที่มีอยู่เดิม โดยคำนวณค่าในแต่ละแถวผ่าน Row Context และส่งคืนตารางเดิมพร้อมคอลัมน์ใหม่ต่อท้าย
CROSSJOIN สร้างตารางใหม่โดยการรวมแถวทั้งหมดจากตารางที่ระบุ โดยสร้างทุก Combination ที่เป็นไปได้ ผลลัพธ์คือตารางที่มีจำนวนแถวเท่ากับผลคูณของจำนวนแถวของแต่ละตาราง
DATATABLE สร้างตารางแบบ hardcode ด้วยข้อมูลคงที่ โดยระบุชื่อคอลัมน์ ชนิดข้อมูล และค่าของแต่ละแถว เหมาะสำหรับตารางอ้างอิงเล็กๆ เช่น lookup table หรือข้อมูลตัวอย่าง
EXCEPT คืนตารางของแถวที่อยู่ใน LeftTable แต่ไม่อยู่ใน RightTable เหมาะกับการหาสิ่งที่ขาดหาย เช่น สินค้าที่ไม่เคยขาย ลูกค้าที่ไม่มีธุรกรรม
GENERATE วนทีละแถวใน Table1 แล้วประเมิน Table2 ในบริบทของแถวนั้น (row context) จากนั้นรวมผลทั้งหมดเป็นตารางเดียว ถ้า Table2 ว่างเปล่าในรอบไหน แถวนั้นจาก Table1 จะถูกตัดออก (ต่างจาก GENERATEALL)
GENERATEALL วนแถวของตาราง 1 แล้วสร้าง Cartesian product กับผลลัพธ์ของตาราง 2 โดยคงแถวที่ไม่มีข้อมูลย่อย ต่างจาก GENERATE ตรงที่ไม่ตัดแถวหลักออก
CONTAINS ค้นหาแถวในตารางและคืนค่า TRUE/FALSE เมื่อหาเจอค่าที่ตรงกับเงื่อนไขที่กำหนด เจ๋งเพราะมันเร็วกว่า COUNTROWS + FILTER มาก
CONTAINSROW ตรวจสอบว่ามีแถวที่ค่าคอลัมน์ตรงกันหมดหรือไม่ ถ้าเจอจะคืนค่า TRUE ไม่มีจะคืน FALSE
CONTAINSSTRING ตรวจสอบว่าข้อความหนึ่งมีข้อความอื่นเป็นส่วนหนึ่งหรือไม่ แล้วคืนค่า TRUE หรือ FALSE ตัวเลือกนี้ไม่สนใจตัวพิมพ์ใหญ่เล็ก
EVALUATEANDLOG คำนวณนิพจน์และส่งผลลัพธ์ไปยัง log สำหรับการตรวจสอบและดีบัก ทำให้เห็นค่าระหว่างกลางของการคำนวณ DAX โดยไม่ต้องเขียนตารางชั่วคราว
AVERAGEX เป็น Iterator Function ที่วนลูปตารางทีละแถว คำนวณ Expression แล้วนำผลลัพธ์มาหาค่าเฉลี่ย เหมาะสำหรับกรณีที่ต้องการเฉลี่ยค่าที่คำนวณได้ เช่น ราคา×จำนวน หรือค่าเฉลี่ยของ Measure ในแต่ละกลุ่ม
COUNTAX ประเมินนิพจน์ต่อแถวในตาราง แล้วนับจำนวนผลลัพธ์ที่ไม่ว่าง เหมาะกับการนับค่าที่อาจเป็นข้อความ ตรรกะ หรือนิพจน์ที่ซับซ้อน ไม่ใช่แค่ตัวเลข
COUNTROWS เป็นฟังก์ชันการรวม (Aggregation) ที่นับจำนวนแถวในตารางที่ระบุ ไม่ว่าจะเป็นตารางจริงในโมเดลหรือตารางเสมือน (Virtual Table) จากฟังก์ชันอื่นๆ เช่น FILTER, VALUES, DISTINCT นับเท่าไหร่? ผลลัพธ์ก็คือจำนวนแถวเต็ม ๆ
ตรวจสอบว่าเงื่อนไขตรรกะทั้งหมดเป็นจริงหรือไม่ และคืนค่า TRUE เมื่อทุกเงื่อนไขเป็น TRUE
CROSSFILTER กำหนดทิศทางการกรองข้ามความสัมพันธ์ระหว่าง 2 คอลัมน์ชั่วคราว (มักใช้ใน CALCULATE) เพื่อควบคุมการไหลของตัวกรองหรือปิดการกรองข้ามในบางการคำนวณ
EXTERNALMEASURE ใช้สำหรับการวิเคราะห์ข้อมูล DAX
FIRSTNONBLANKVALUE คืนค่าแรกที่ไม่เป็น BLANK ของ Expression เมื่อประเมินตามลำดับของ Column ซึ่งมีประโยชน์ในการหาค่าเริ่มต้นหรือค่าแรกที่มีข้อมูลจริง เช่นยอดขายของวันแรกที่มีการขาย
NATURALJOINUSAGE ทำให้ table expression ถูกเพิ่มเข้าไปในตัวกรอง (filter context) แบบ natural join โดยจับคู่ตามคอลัมน์ชื่อเดียวกัน เป็นฟังก์ชันที่ออกแบบสำหรับการใช้งานขั้นสูงในโมเดลแบบประกอบ (composite models) และ SUMMARIZECOLUMNS
ROLLUP บอก SUMMARIZE ให้สร้างแถว subtotal เพิ่มเติมตามคอลัมน์ที่กำหนด ทำให้ได้ทั้งรายละเอียดและรวมย่อยในผลลัพธ์เดียว
ฟังก์ชันเชิงเครื่องมือสำหรับเลือกจำนวนแถวสูงสุด (Top N) ต่อ ระดับในโครงสร้างลำดับชั้น (hierarchy) ที่มีการขยาย/ยุบโหนด
ดึงแถวจากตารางโดยข้ามจำนวนแถวที่กำหนดก่อน แล้วคืนแถวถัดไปตามการเรียงลำดับที่ระบุ มีประสิทธิภาพสูงสำหรับงาน pagination
TREATAS เป็นเสมือนการสร้าง "virtual relationship" โดยไม่ต้องแก้โมเดล ช่วยให้ส่งเงื่อนไขข้ามตารางที่ไม่เชื่อมกัน หรือเมื่อต้องการส่งหลายคีย์พร้อมกัน
KEEPFILTERS เป็นฟังก์ชันปรับตัวกรองที่ใช้ภายใน CALCULATE เพื่อ “คงตัวกรองเดิมไว้” แล้วนำตัวกรองใหม่มารวมกันแบบ AND (ตัดกันเฉพาะส่วนที่ตรงกัน) แทนพฤติกรรมปกติที่มักเขียนทับตัวกรองเดิมของคอลัมน์เดียวกัน
LOOKUP ค้นหาและดึงค่าจากเมทริกซ์ภาพ (visual matrix) ในการคำนวณภาพโดยการระบุเงื่อนไขการกรอง ใช้เฉพาะในการคำนวณภาพเท่านั้น
LOOKUPVALUE เป็นฟังก์ชันค้นหาที่ยืดหยุ่น โดยจะดึงค่าจากคอลัมน์หนึ่งโดยการค้นหาตามเงื่อนไขหลายตัวในเวลาเดียวกัน
REMOVEFILTERS ลบ Filter ออกจากตารางหรือคอลัมน์ที่ระบุ ใช้ได้ใน CALCULATE เท่านั้น เทียบเท่า ALL เมื่อใช้เป็น CALCULATE Modifier แต่ชัดเจนและอ่านโค้ดง่ายกว่า แนะนำใช้แทน ALL เพราะสื่อความหมายได้ดีกว่า
ตรวจว่าคอลัมน์ถูก filter โดยตรงให้เหลือค่าเดียวหรือไม่ เหมาะกับการควบคุมการแสดงผลตามสถานะการเลือกของผู้ใช้
MEDIANX คำนวณค่ามัธยฐาน (50th Percentile) ของนิพจน์ที่ประเมินในแต่ละแถว ต่างจาก MEDIAN ที่ทำงานบนคอลัมน์เดียว MEDIANX คือ iterator function ที่ให้คุณสร้างนิพจล์ซับซ้อนก่อนหาค่ากลาง
Comments
อีเมลของคุณจะไม่ถูกเผยแพร่