---
title: IF – ตรวจสอบเงื่อนไขและคืนค่าตามผลลัพธ์ TRUE/FALSE
url: https://www.thepexcel.com/functions/dax/logical/if-dax/
type: function-explainer
program: DAX
syntax: "IF(<logical_test>, <value_if_true>[, <value_if_false>])"
date: 2025-12-18
scores:
  popularity: 10
  difficulty: 2
  usefulness: 10
---

# IF – ตรวจสอบเงื่อนไขและคืนค่าตามผลลัพธ์ TRUE/FALSE

> ตรวจสอบเงื่อนไขแล้วคืนค่าตามผลลัพธ์ TRUE หรือ FALSE

## คำอธิบาย

IF เป็นฟังก์ชันตรรกะพื้นฐานที่สำคัญที่สุดใน DAX ใช้สำหรับตรวจสอบเงื่อนไข (logical test) แล้วคืนค่าที่แตกต่างกันตามผลลัพธ์ว่าเป็นจริง (TRUE) หรือเท็จ (FALSE) สามารถใช้ได้ทั้งในบริบท calculated column, measure, calculated table และ visual calculation ซึ่งทำให้มีความยืดหยุ่นสูง คืนค่าเป็น scalar value ได้ทุกประเภท ไม่ว่าจะเป็นตัวเลข ข้อความ วันที่ หรือค่า boolean ถ้าไม่ระบุค่าสำหรับกรณีเท็จ (value_if_false) จะคืน BLANK() โดยอัตโนมัติ มีคุณสมบัติพิเศษคือ lazy evaluation behavior ที่ประมวลผลเฉพาะเส้นทาง (branch) ที่ถูกเลือกเท่านั้น ทำให้มีประสิทธิภาพในการทำงานที่ดี แตกต่างจาก Excel IF อย่างชัดเจนตรงที่ใช้รูปแบบอ้างอิงแบบ Table[Column] ทำงานภายใต้ filter context และแยกความแตกต่างระหว่าง BLANK กับ 0 อย่างเข้มงวด

## Syntax

```excel
IF(&lt;logical_test&gt;, &lt;value_if_true&gt;[, &lt;value_if_false&gt;])
```

**Variant**

```excel
IF(&lt;logical_test&gt;, &lt;value_if_true&gt;)
```

รูปแบบพื้นฐาน - ถ้าเงื่อนไขเป็นจริงคืนค่าที่กำหนด ถ้าเป็นเท็จจะคืน BLANK() โดยอัตโนมัติ ใช้เมื่อต้องการซ่อนค่าที่ไม่ตรงเงื่อนไข เหมาะกับการแสดงผลใน visual เพราะ BLANK ไม่แสดงใน chart และไม่นับใน aggregation บางประเภท

**Variant**

```excel
IF(&lt;logical_test&gt;, &lt;value_if_true&gt;, &lt;value_if_false&gt;)
```

รูปแบบเต็ม - กำหนดค่าที่คืนทั้งกรณีจริงและเท็จ ทำให้ควบคุมผลลัพธ์ได้ครบทั้งสองทาง เหมาะกับการจัดกลุ่มข้อมูล (segmentation) การสร้าง KPI label หรือการแปลงค่าตัวเลขเป็นข้อความสถานะ

**Variant**

```excel
IF(Sales[Amount] &gt; 1000, "High", "Low")
```

Pattern: Segmentation ใน calculated column - เปรียบเทียบค่าใน column กับ threshold แล้วคืนข้อความสถานะ ทำงานใน row context โดย evaluate แต่ละ row ของ table ผลลัพธ์สามารถนำไปใช้เป็น slicer หรือ filter ได้

**Variant**

```excel
IF([Total Sales] &gt;= [Sales Target], "ผ่าน", "ไม่ผ่าน")
```

Pattern: KPI Status Label - เปรียบเทียบ measure กับ measure อื่น เหมาะกับการสร้าง performance indicator ใน card หรือ table ที่เปลี่ยนแปลงตาม filter context ของ visual

**Variant**

```excel
IF(HASONEVALUE(Products[ProductName]), [Average Price], BLANK())
```

Pattern: Hide Total Level - ตรวจสอบ filter context ด้วย HASONEVALUE เพื่อแสดงค่าเฉพาะระดับ detail ซ่อนค่าในระดับ total/subtotal ป้องกัน average of averages หรือค่าที่ไม่มีความหมายในภาพรวม

**Variant**

```excel
IF(condition1 &amp;&amp; condition2, result1, result2)
```

Pattern: Complex Boolean Logic - ใช้ && (AND) หรือ || (OR) เพื่อรวมหลายเงื่อนไข ทำให้โค้ดกระชับและมี performance ดีกว่าใช้ AND()/OR() function เพราะ DAX engine optimize logical operator ได้ดีกว่า

**Variant**

```excel
VAR Sales = [Total Sales]
RETURN IF(Sales &gt; 100000, Sales * 0.1, Sales * 0.05)
```

Pattern: VAR Optimization - ใช้ VAR เพื่อคำนวณค่าที่ใช้ซ้ำก่อน IF ป้องกันการคำนวณซ้ำซ้อนใน condition และ result branches เพิ่ม performance และทำให้โค้ดอ่านง่ายขึ้น

## Arguments

| Name | Required | Type | Default | Description |
| --- | --- | --- | --- | --- |
| logical_test | Yes | boolean |  | เงื่อนไขตรรกะที่ต้องการตรวจสอบ สามารถเป็น expression ใดก็ได้ที่ evaluate ออกมาเป็น TRUE หรือ FALSE เช่น Sales[Amount] > 1000, Products[Category] = "Electronics", [Total Profit] >= 0 หรือใช้ร่วมกับ logical operator && (AND), \|\| (OR), ! (NOT) ใน row context (calculated column) จะ evaluate แต่ละ row ของ table โดยใช้ค่าจาก column นั้นๆ ใน filter context (measure) จะ evaluate ตาม filter ปัจจุบันของ visual สามารถใช้ ISBLANK, HASONEVALUE, HASONEFILTER หรือ logical function อื่นๆ ได้ ถ้า logical_test evaluate เป็น BLANK จะถือว่าเป็น FALSE |
| value_if_true | Yes | scalar |  | ค่าที่ต้องการคืนเมื่อเงื่อนไขเป็น TRUE สามารถเป็นตัวเลข ข้อความ วันที่ boolean ผลลัพธ์จาก measure อื่น หรือ expression ที่คำนวณได้ เช่น "High", 100, [Total Sales] * 1.1, BLANK() ถ้า value_if_true และ value_if_false มี data type ต่างกัน DAX จะคืนเป็น VARIANT type และอาจแปลง type โดยอัตโนมัติ (เช่น integer เป็น decimal เมื่อมี branch ใดเป็น decimal, boolean เป็น integer) ถ้า expression ซับซ้อน แนะนำให้ใช้ VAR เก็บค่าก่อนแล้วค่อย reference ใน IF เพื่อ performance และ readability ที่ดีขึ้น เนื่องจาก IF มี lazy evaluation value_if_true จะถูก evaluate เฉพาะเมื่อ logical_test เป็น TRUE |
| value_if_false | No | scalar | BLANK() | ค่าที่ต้องการคืนเมื่อเงื่อนไขเป็น FALSE ถ้าไม่ระบุจะคืน BLANK() โดยอัตโนมัติ ซึ่งมักใช้เพื่อ "ซ่อน" ผลลัพธ์ในบางกรณี เช่น ซ่อนค่าในระดับ total หรือซ่อนค่าที่ไม่มีความหมาย BLANK ใน DAX มีลักษณะพิเศษ: ไม่แสดงใน visual (cell ว่าง), ไม่นับรวมใน AVERAGE (ข้าม BLANK ไปเลย), มี propagation rule (BLANK + 5 = 5, BLANK * 5 = BLANK) สามารถเป็น data type เดียวกันหรือต่างจาก value_if_true ได้ แต่ VARIANT return type อาจส่งผลต่อ performance และ memory usage ในบางกรณี เนื่องจาก lazy evaluation value_if_false จะถูก evaluate เฉพาะเมื่อ logical_test เป็น FALSE |

## เคสการใช้งาน

### สร้าง KPI Label และ Status Indicator

แปลงผลการคำนวณตัวเลขให้เป็นข้อความสถานะ (ผ่าน/ไม่ผ่าน, สูง/กลาง/ต่ำ) หรือสถานะ emoji เพื่อใช้ใน card, table หรือเป็น conditional formatting condition ทำให้รายงานอ่านง่ายและเข้าใจได้ทันที เหมาะกับ executive dashboard ที่ผู้บริหารต้องการเห็นสถานะชัดเจนโดยไม่ต้องตีความตัวเลข

_เหมาะกับ:_ kpi-label

### ซ่อนค่าในระดับ Total/Subtotal

คืน BLANK() เมื่ออยู่ในระดับรวม (total/subtotal) เพื่อไม่แสดงค่าที่ไม่มีความหมายในภาพรวม เช่น average of averages (ค่าเฉลี่ยของค่าเฉลี่ยไม่ถูกต้อง), ratio ที่ควรคำนวณจาก total numerator/total denominator ไม่ใช่ average ของ ratio, margin % ที่ต้องคำนวณจาก aggregated values ใช้ HASONEVALUE, HASONEFILTER, ISINSCOPE หรือ ISFILTERED เพื่อตรวจสอบว่าอยู่ใน detail level หรือไม่

_เหมาะกับ:_ hide-total

### Data Segmentation - จัดกลุ่มข้อมูล

สร้างกลุ่มเช่น Low/Medium/High, A/B/C grade, age group (18-25, 26-35), customer segment (VIP/Regular/New) จากเงื่อนไขที่กำหนด แล้วนำไปใช้เป็น slicer, axis หรือ legend ใน visual ช่วยให้วิเคราะห์ข้อมูลตาม cohort ได้ง่ายขึ้น สร้าง RFM analysis, ABC analysis หรือ customer lifetime value segment มักใช้ใน calculated column เพื่อให้ segment เป็นส่วนหนึ่งของ data model

_เหมาะกับ:_ segmentation

### Handle Missing Data และ Edge Cases

ตรวจสอบและจัดการข้อมูลที่ขาดหาย (BLANK, NULL) หรือกรณีพิเศษ เช่น division by zero, ค่าที่อยู่นอกช่วง (outlier), data quality issue ถ้าไม่มีข้อมูลให้ใช้ค่า default หรือคืน BLANK เพื่อป้องกัน error หรือผลลัพธ์ที่ผิดพลาด เช่น IF(ISBLANK([Sales]), 0, [Sales]) หรือใช้ IF ร่วมกับ DIVIDE, COALESCE เพื่อสร้าง robust measure ที่ทำงานได้แม้มีข้อมูลไม่ครบ

_เหมาะกับ:_ data-quality

### Dynamic Calculation Logic

เปลี่ยนวิธีการคำนวณตาม filter context, user selection ใน slicer หรือเงื่อนไขที่กำหนด เช่น ถ้าเลือก View = "YTD" ให้คำนวณแบบ year-to-date ถ้าเลือก "MTD" ให้คำนวณแบบ month-to-date หรือสลับระหว่าง Actual vs Budget calculation, Standard vs Custom formula ทำให้ measure เดียวรองรับหลาย scenario ลดจำนวน measure ที่ต้อง maintain และให้ user มี flexibility ในการวิเคราะห์

_เหมาะกับ:_ dynamic-logic

### Conditional Formatting Logic

สร้าง logic เพื่อควบคุม conditional formatting ของ visual เช่น ถ้ายอดขายต่ำกว่า target แสดงสีแดง ถ้ามากกว่าแสดงสีเขียว หรือใช้ icon set ตามระดับ performance (⬆️⬇️➡️) หรือแสดง warning indicator เมื่อมี data anomaly ทำให้ visual มี visual cue ที่ชัดเจน ช่วย user spot issue หรือ highlight achievement ได้ทันที

_เหมาะกับ:_ conditional-formatting

## ตัวอย่าง

### 1. ตัวอย่างที่ 1: Foundation - จัดกลุ่มราคาสินค้าใน Calculated Column

```excel
-- Calculated Column ใน Products table
Price Group = 
IF(
    Products[List Price] < 500,
    "Low",
    "High"
)

-- Context:
-- Products table มี columns: ProductID, Product Name, List Price, Category
-- ตัวอย่างข้อมูล:
-- | ProductID | Product Name | List Price | Price Group |
-- | 1         | Widget A     | 250        | Low         |
-- | 2         | Widget B     | 750        | High        |
-- | 3         | Gadget X     | 450        | Low         |
```

**ผลลัพธ์:** `คืน "Low" ถ้าราคาต่ำกว่า 500 มิฉะนั้นคืน "High" - Column ใหม่ที่แสดงกลุ่มราคาของแต่ละสินค้า`

Calculated column ทำงานใน row context ดังนั้น IF จะ evaluate แต่ละ row ของ Products table โดยตรวจสอบค่าใน List Price column ของ row นั้นๆ ถ้าราคาต่ำกว่า 500 จะ assign ค่า "Low" ให้ row นั้น ถ้าไม่ใช่จะได้ "High"
.
ผลลัพธ์คือ column ใหม่ชื่อ "Price Group" ที่เก็บกลุ่มราคาไว้ สามารถนำไปใช้เป็น slicer, filter ใน visual หรือ axis ใน chart ได้ทันที ส่วนตัวผมว่านี่เป็นวิธีที่ง่ายที่สุดในการจัดกลุ่มข้อมูลครับ 😎
.
Column นี้เป็นส่วนหนึ่งของ data model และคำนวณ 1 ครั้งตอน refresh data ไม่ใช่ dynamic ตาม filter (ต่างจาก measure) เหมาะกับกรณีที่ต้องการ fixed grouping ที่ไม่เปลี่ยนแปลง

### 2. ตัวอย่างที่ 2: Practical - ซ่อนค่าเฉลี่ยในระดับ Total

```excel
-- Measure ที่แสดงค่าเฉพาะระดับ detail
Average Unit Price (Detail Only) = 
IF(
    HASONEVALUE(Products[Product Name]),
    AVERAGE(Sales[Unit Price]),
    BLANK()
)

-- Context:
-- Sales table มี columns: OrderID, ProductID, Unit Price, Quantity, Date
-- Products table มี: ProductID, Product Name, Category
-- Relationship: Sales[ProductID] → Products[ProductID]

-- ผลลัพธ์ใน Matrix visual:
-- | Product Name | Avg Unit Price |
-- | Product A    | 125.50         |
-- | Product B    | 89.25          |
-- | Product C    | 156.00         |
-- | Total        | (blank)        | ← ซ่อนเพราะไม่มีความหมาย
```

**ผลลัพธ์:** `แสดงราคาเฉลี่ยเฉพาะระดับสินค้าแต่ละตัว ซ่อนค่าในระดับ total/subtotal (แสดงเป็น cell ว่าง)`

HASONEVALUE ตรวจสอบว่า filter context ปัจจุบันมีสินค้าเดียวหรือไม่ ถ้ามี (user กำลังดูระดับสินค้าแต่ละตัว = detail level) จะคำนวณ AVERAGE(Sales[Unit Price]) ปกติ แต่ถ้าไม่มี (อยู่ใน total/subtotal row ที่มีหลายสินค้ารวมกัน) จะคืน BLANK() เพื่อไม่แสดงค่า
.
เหมาะกับกรณีที่ค่าเฉลี่ยในระดับรวมไม่มีความหมาย เพราะ average of averages ไม่ถูกต้อง (แต่ละสินค้ามีจำนวน transaction ไม่เท่ากัน) 😅
.
วิธีนี้ทำให้ matrix visual มี cell ว่างใน total row แทนที่จะแสดงค่าที่เข้าใจผิดได้ BLANK ใน DAX ไม่เท่ากับ 0 และจะไม่แสดงใน visual (แตกต่างจาก Excel)

### 3. ตัวอย่างที่ 3: Advanced - เงื่อนไขซับซ้อนด้วย Logical Operators

```excel
-- Measure สำหรับจัดกลุ่ม customer segment
Customer Segment = 
VAR TotalSales = [Total Sales Amount]
VAR TotalProfit = [Total Profit]
VAR ProfitMargin = DIVIDE(TotalProfit, TotalSales, 0)
RETURN
    IF(
        TotalSales > 100000 && ProfitMargin > 0.2,
        "High Value",
        IF(
            TotalSales > 50000 || ProfitMargin > 0.15,
            "Medium Value",
            "Standard"
        )
    )

-- Context:
-- Sales table มี: CustomerID, Amount, Cost, Date
-- [Total Sales Amount] = SUM(Sales[Amount])
-- [Total Profit] = SUM(Sales[Amount]) - SUM(Sales[Cost])

-- ตัวอย่างผลลัพธ์:
-- | Customer | Total Sales | Profit Margin | Segment      |
-- | ABC Corp | 150,000     | 25%          | High Value   |
-- | XYZ Inc  | 60,000      | 12%          | Medium Value |
-- | 123 Ltd  | 30,000      | 8%           | Standard     |
```

**ผลลัพธ์:** `คืน "High Value" เมื่อยอดขายสูงและ margin ดี, "Medium Value" เมื่อผ่านเงื่อนไขใดเงื่อนไขหนึ่ง, มิฉะนั้นคืน "Standard"`

ตัวอย่างนี้แสดงการใช้ VAR ร่วมกับ IF และ logical operators (&&, ||) เพื่อสร้าง segmentation logic ที่ซับซ้อน
.
ขั้นแรกใช้ VAR คำนวณค่าที่ต้องใช้ซ้ำ (TotalSales, TotalProfit, ProfitMargin) เพื่อป้องกันการคำนวณซ้ำและทำให้โค้ดอ่านง่าย ใน IF ชั้นแรกใช้ && (AND operator) เช็คว่ายอดขายมากกว่า 100,000 AND margin มากกว่า 20% ถึงจะเป็น "High Value"
.
ถ้าไม่ผ่านเงื่อนไขแรก จะเช็ค IF ชั้นที่สอง ซึ่งใช้ || (OR operator) ถ้ายอดขายมากกว่า 50,000 OR margin มากกว่า 15% (เงื่อนไขใดเงื่อนไขหนึ่งผ่านก็พอ) จะได้ "Medium Value" ถ้าไม่ผ่านทั้งสองจะได้ "Standard"
.
วิธีนี้ดีกว่าใช้ AND()/OR() function เพราะกระชับกว่าและ DAX engine optimize logical operator ได้ดีกว่า 😎

### 4. ตัวอย่างที่ 4: Advanced - Dynamic Time Intelligence

```excel
-- Measure ที่เปลี่ยน calculation logic ตาม user selection
Dynamic Sales = 
VAR SelectedPeriod = SELECTEDVALUE(PeriodType[Period], "Current")
VAR CurrentSales = [Total Sales Amount]
RETURN
    SWITCH(
        SelectedPeriod,
        "YTD", CALCULATE(CurrentSales, DATESYTD(Calendar[Date])),
        "MTD", CALCULATE(CurrentSales, DATESMTD(Calendar[Date])),
        "QTD", CALCULATE(CurrentSales, DATESQTD(Calendar[Date])),
        CurrentSales  -- Default: Current period
    )

-- Alternative ด้วย IF (ไม่แนะนำ - ใช้ SWITCH ดีกว่า):
Dynamic Sales IF Version = 
VAR SelectedPeriod = SELECTEDVALUE(PeriodType[Period], "Current")
RETURN
    IF(
        SelectedPeriod = "YTD",
        CALCULATE([Total Sales Amount], DATESYTD(Calendar[Date])),
        IF(
            SelectedPeriod = "MTD",
            CALCULATE([Total Sales Amount], DATESMTD(Calendar[Date])),
            [Total Sales Amount]
        )
    )

-- Context:
-- PeriodType table (disconnected table สำหรับ slicer): Period = {"Current", "MTD", "QTD", "YTD"}
-- Calendar table มี: Date, Year, Month, Quarter
-- Sales table มี: Amount, Date
-- Relationship: Sales[Date] → Calendar[Date]
```

**ผลลัพธ์:** `แสดง Current/MTD/QTD/YTD sales ตามที่ user เลือกใน PeriodType slicer - Measure เดียวรองรับหลาง time intelligence pattern`

ตัวอย่างนี้แสดงการสร้าง dynamic measure ที่เปลี่ยน calculation logic ตาม user selection โดยใช้ SELECTEDVALUE ดึงค่าที่เลือกจาก PeriodType slicer (ถ้าไม่เลือกหรือเลือกหลายค่าจะได้ default "Current")
.
จากนั้นใช้ SWITCH เปรียบเทียบ SelectedPeriod กับค่าต่างๆ แล้วเรียก time intelligence function ที่เหมาะสม ถ้าเลือก "YTD" จะใช้ DATESYTD คำนวณ year-to-date ถ้า "MTD" ใช้ DATESMTD สำหรับ month-to-date และถ้าไม่ตรงกรณีไหนจะแสดง current period sales ปกติ
.
วิธีนี้ทำให้ measure เดียวรองรับหลาย scenario ลดจำนวน measure ที่ต้อง maintain 😎
.
ตัวอย่างยังแสดงวิธีเขียนด้วย nested IF (IF Version) เพื่อเปรียบเทียบ แต่ชัดเจนว่า SWITCH อ่านง่ายกว่าและแนะนำให้ใช้สำหรับกรณีที่มีหลายทางเลือก

## หมายเหตุเพิ่มเติม

💡 **Best Practices ที่ผมแนะนำ:**
.
1) ใช้ VAR เพื่อคำนวณค่าที่ใช้ซ้ำ วาง VAR ก่อน IF ถ้าใช้ใน logical_test หรือทั้งสอง branch เพื่อป้องกันการคำนวณซ้ำซ้อน
2) ใช้ && / || แทน AND()/OR() เพื่อให้โค้ดกระชับและ DAX engine optimize ได้ดีกว่า (ส่วนตัวผมใช้แบบนี้เสมอครับ)
3) พิจารณา SWITCH เมื่อเงื่อนไขมากกว่า 2-3 ระดับ เพื่อ readability และ maintainability ที่ดีกว่า
4) สำหรับการหารใช้ DIVIDE แทน IF pattern เสมอ เพราะ performance และ robustness ดีกว่ามากครับ 😎
5) ระวัง data type conversion - ถ้า value_if_true และ value_if_false เป็น type ต่างกัน DAX จะคืนเป็น VARIANT และอาจแปลง type โดยอัตโนมัติ
.
⚠️ **Performance Tips:**
.
IF มี lazy evaluation (evaluate เฉพาะ branch ที่เลือก) จึงมี performance ดีกว่า IF.EAGER ในเกือบทุกกรณี แต่ nested IF มากกว่า 3 ชั้นยังสร้าง query plan ที่ซับซ้อน ควรใช้ SWITCH หรือ lookup table แทนครับ
.
ส่วนตัวผมแนะนำให้ใช้ DIVIDE แทน IF pattern สำหรับการหาร ใช้ COALESCE แทน IF chain สำหรับ BLANK handling และระวัง context transition cost เมื่อเรียกใช้ measure ภายใน IF ที่อยู่ใน row context เพราะมันกินเวลาคำนวณเยอะมากครับ 😅
.
🔍 **Context Awareness:**
.
IF ใน measure ทำงานภายใต้ filter context ดังนั้นผลลัพธ์จะเปลี่ยนตาม slicer, filter และ visual context (row/column ใน matrix, category ใน chart) ซึ่งเป็นจุดเด่นของ DAX ที่แตกต่างจาก Excel มากๆ ครับ
.
IF ใน calculated column ทำงานใน row context และ evaluate แต่ละ row โดยใช้ค่าจาก column ของ row นั้นๆ ถ้าเรียกใช้ measure ภายใน IF ที่อยู่ใน row context จะเกิด context transition (row context แปลงเป็น filter context) ซึ่งมี performance cost สูง ต้องระวังนะครับ
.
🚀 **Alternatives ที่ดีกว่า IF:**
.
พิจารณาใช้ function อื่นๆ ที่เหมาะสมกว่า IF ในบางกรณี: SWITCH สำหรับหลายเงื่อนไข, SWITCH(TRUE(), ...) แทน nested IF ที่มีเงื่อนไขต่างกัน, DIVIDE สำหรับ division by zero (แนะนำมากๆ), COALESCE สำหรับ null/blank handling chain, IFERROR สำหรับ error handling และ IF.EAGER ถ้าต้องการ eager evaluation (แต่ส่วนตัวผมไม่แนะนำในเกือบทุกกรณีครับ เพราะ lazy evaluation ของ IF ปกติมี performance ดีกว่า)

## คำถามที่พบบ่อย

**Q: ควรใช้ IF หรือ SWITCH ในกรณีไหน?**

ใช้ IF เมื่อมีเงื่อนไข 1-2 ระดับ หรือเงื่อนไข boolean ที่ซับซ้อน (เช่น [Sales] > 1000 && [Profit] > 0) IF ตรงไปตรงมาและเข้าใจง่าย
.
แต่ถ้ามีหลายกรณี (3-5+ ระดับ) ให้ใช้ SWITCH แทนเพราะอ่านง่ายกว่า maintain ง่ายกว่า และมี query plan ที่ดีกว่า (execution path ชัดเจนกว่า nested IF)
.
SWITCH เหมาะกับการเปรียบเทียบ expression เดียวกับค่าหลายค่า (เช่น status = "Active"/"Pending"/"Closed") หรือใช้ SWITCH(TRUE(), condition1, result1, condition2, result2, ...) pattern เพื่อแทน nested IF ที่มีเงื่อนไขต่างกัน
.
ส่วน IF เหมาะกับการตัดสินใจแบบ binary (yes/no) หรือเงื่อนไขที่แต่ละ branch มี logic ที่แตกต่างกันมาก Microsoft และ SQLBI แนะนำให้ใช้ SWITCH เมื่อมีทางเลือกมากกว่า 2-3 ทาง

**Q: ถ้าไม่ใส่ value_if_false จะเกิดอะไรขึ้น?**

IF จะคืนค่า BLANK() โดยอัตโนมัติ BLANK ใน DAX ต่างจาก 0 หรือ empty string ("") อย่างชัดเจน
.
BLANK มีพฤติกรรมพิเศษ 4 ประการ:
1) ไม่แสดงใน visual (จะเห็น cell ว่าง)
2) ไม่นับรวมใน aggregation บางประเภท (AVERAGE จะข้าม BLANK ไม่นับเป็น 0, ส่วน SUM จะนับเป็น 0)
3) มี propagation rule เฉพาะ (BLANK + number = number, BLANK * number = BLANK, BLANK & text = text)
4) BLANK ใน logical expression ถือว่าเป็น FALSE
.
วิธีนี้มักใช้เพื่อ "ซ่อน" ผลลัพธ์ในบางกรณี เช่น IF(condition, result) จะแสดง result เฉพาะตอนที่ condition เป็นจริง มิฉะนั้นจะไม่แสดงอะไร (cell ว่าง)
.
แตกต่างจาก IF(condition, result, 0) ที่จะแสดง 0 เมื่อ condition เป็นเท็จ การเลือกใช้ BLANK vs 0 ส่งผลต่อการแสดงผลและการคำนวณ aggregation อย่างมาก

**Q: Nested IF ควรซ้อนกี่ชั้น และทำไมต้องระวัง?**

ทางเทคนิคซ้อนได้ไม่จำกัด แต่ถ้าซ้อนมากกว่า 3 ชั้นจะมีปัญหา 4 อย่าง:
.
1) **Readability** - โค้ดอ่านยาก maintain ยาก debug ยาก วงเล็บเยอะ 😭
2) **Performance** - แม้ว่า IF มี lazy evaluation (evaluate เฉพาะ branch ที่เลือก) แต่ nested IF มากๆ ยังทำให้ query engine สร้าง execution plan ที่ซับซ้อนและ optimize ยากกว่า flat structure
3) **Error-prone** - ความเสี่ยงที่จะเขียนเงื่อนไขผิด ลืมวงเล็บ หรือวาง logic ผิดลำดับสูงขึ้น
4) **Testing** - ทดสอบยากเพราะมีหลาย code path
.
ถ้ามีเงื่อนไขหลายระดับ แนะนำใช้ SWITCH แทน (SWITCH อ่านง่ายกว่ามาก) หรือแยกเป็น VAR หลายตัวเพื่อให้ logic ชัดเจนขึ้น หรือสร้าง lookup table แทนการใช้ hardcoded conditions ทั้งหมด
.
**Best practice:** ถ้าเกิน 2-3 ชั้น ให้หยุดคิดก่อนว่ามีวิธีอื่นที่ดีกว่าไหม (SWITCH, lookup table, หรือแยก logic ออกเป็นหลาย measure)

**Q: IF ใน DAX ต่างจาก Excel IF อย่างไร?**

แม้ว่า logic เหมือนกัน (ตรวจสอบเงื่อนไขแล้วคืนค่า) แต่มีความแตกต่างสำคัญ 6 ประการ:
.
1) **Reference Style** - DAX ใช้ Table[Column] reference (Sales[Amount]) ไม่มี cell range A1:A10 เพราะทำงานกับ data model ไม่ใช่ spreadsheet
2) **Context Awareness** - IF ใน DAX measure ทำงานภายใต้ filter context และเปลี่ยนผลลัพธ์ตาม slicer/filter/visual context ส่วน Excel IF คำนวณเฉพาะเซลล์นั้น
3) **Context Transition** - DAX ทำ context transition อัตโนมัติใน row context (calculated column) ส่วน Excel ไม่มีแนวคิดนี้
4) **BLANK vs 0** - DAX แยก BLANK() กับ 0 ชัดเจน มี propagation rule และ aggregation behavior ต่างกัน ส่วน Excel มักแปลง empty cell เป็น 0
5) **Evaluation** - DAX IF มี lazy evaluation (evaluate เฉพาะ branch ที่เลือก) ส่วน Excel มี short-circuit evaluation แบบเต็มรูปแบบ
6) **Alternatives** - DAX มี SWITCH, DIVIDE, COALESCE ที่เป็น alternative ที่ดีกว่า nested IF ส่วน Excel ไม่มี (Excel มี IFS แต่ไม่เหมือน SWITCH)

**Q: ใช้ VAR กับ IF อย่างไรให้มี Performance ดี?**

การใช้ VAR ร่วมกับ IF มีประโยชน์มากแต่ต้องวางตำแหน่งให้ถูก มี 3 แนวทางหลัก:
.
**1) VAR ก่อน IF (แนะนำ)** - ใช้เมื่อค่านั้นถูกใช้ใน logical_test หรือใช้ทั้ง true และ false branch
เช่น `VAR Sales = [Total Sales] RETURN IF(Sales > 1000, Sales * 0.1, Sales * 0.05)`
วิธีนี้คำนวณแค่ครั้งเดียวและ cache ค่าไว้ เนื่องจาก IF มี lazy evaluation จึงไม่เสีย performance
.
**2) VAR ภายใน Branch** - ใช้เมื่อค่านั้นใช้เฉพาะใน branch ใดบ branch หนึ่ง
เช่น `IF(condition, (VAR x = [ComplexCalc] RETURN x * 2), [SimpleCalc])`
วิธีนี้ทำให้ VAR ถูก evaluate เฉพาะเมื่อ branch นั้นถูกเลือก ประหยัด computation
.
**3) VAR สำหรับ Intermediate Result** - แยก complex expression เป็น VAR หลายตัวเพื่อให้โค้ดอ่านง่ายและ debug ง่าย
.
ประโยชน์: คำนวณแค่ครั้งเดียว (ไม่ซ้ำ), query engine optimize ได้ดีกว่า, โค้ดอ่านง่าย, debug ง่าย แต่อย่าใช้ VAR มากเกินไปจนโค้ดยาวเกินจำเป็น 😅

**Q: IF มี Lazy Evaluation จริงหรือ และต่างจาก IF.EAGER อย่างไร?**

ใช่! DAX IF มี lazy evaluation โดย default ซึ่งหมายความว่า IF จะ evaluate เฉพาะ branch ที่ถูกเลือกตาม logical test ไม่ evaluate ทั้งสอง branch พร้อมกัน
.
ตัวอย่าง: `IF([Sales] > 1000, [Expensive Calculation A], [Expensive Calculation B])`
ถ้า [Sales] > 1000 เป็นจริง มันจะคำนวณเฉพาะ [Expensive Calculation A] ไม่คำนวณ B นี่คือข้อได้เปรียบด้าน performance ของ IF 😎
.
ตรงข้ามกับ **IF.EAGER** ซึ่ง evaluate ทั้งสอง branch ก่อนตัดสินใจเลือก (eager evaluation) IF.EAGER มีไว้สำหรับกรณีพิเศษที่ต้องการให้ query engine เห็น execution plan ของทั้งสอง branch เพื่อ optimize ได้ดีกว่า แต่ส่วนใหญ่ไม่ควรใช้ เพราะ lazy evaluation ของ IF ปกติมี performance ดีกว่าในเกือบทุกกรณี
.
**Caveat:** แม้จะเป็น lazy evaluation แต่ DAX engine อาจ evaluate บาง expression ล่วงหน้าเพื่อ optimization จึงไม่ควรพึ่งพา lazy evaluation เพื่อป้องกัน error (ควรใช้ IFERROR หรือ DIVIDE แทน)

**Q: ทำไม DIVIDE ถึงดีกว่า IF สำหรับการหาร?**

สำหรับการหารที่ต้องการ handle division by zero แนะนำให้ใช้ DIVIDE แทน IF pattern เสมอ เหตุผล 4 ประการ:
.
**1) Performance** - `DIVIDE(numerator, denominator, alternate_result)` มี built-in zero-division handling ที่ query engine optimize ได้ดีกว่า `IF(denominator  0, numerator/denominator, alternate_result)` เพราะ DIVIDE ถูกออกแบบมาเฉพาะ
.
**2) Readability** - DIVIDE กระชับกว่า อ่านง่ายกว่า เห็นเจตนาชัดเจนกว่า ("this is division with safe handling")
.
**3) Handles BLANK** - DIVIDE จัดการ BLANK ใน denominator ได้โดยอัตโนมัติ (คืน alternate_result) ส่วน IF ต้องเช็คทั้ง  0 และ NOT(ISBLANK())
.
**4) Robust** - DIVIDE จัดการ edge case อื่นๆ ที่อาจพลาดใน IF (เช่น infinity, very small numbers)
.
ตัวอย่าง: `DIVIDE([Total Profit], [Total Sales], BLANK())` ดีกว่า `IF([Total Sales]  0, [Total Profit]/[Total Sales], BLANK())`
.
และถ้าไม่ระบุ alternate_result (argument ที่ 3) DIVIDE จะคืน BLANK โดย default Microsoft และ SQLBI แนะนำให้ใช้ DIVIDE เสมอสำหรับการหาร ไม่ใช้ IF pattern เว้นแต่มี logic พิเศษที่ซับซ้อนกว่า

## ฟังก์ชันที่เกี่ยวข้อง

- [SWITCH – คืนค่าตามหลายกรณี ปลดปล่อยตัวเองจาก IF ซ้อน](https://www.thepexcel.com/functions/dax/logical/switch-dax/)
- [AND – ตรวจสอบเงื่อนไขตรรกะในDAX](https://www.thepexcel.com/functions/dax/logical/and-dax/)
- [OR – ตรวจสอบว่ามีเงื่อนไขใดเป็นจริง](https://www.thepexcel.com/functions/dax/logical/or-dax/)
- [NOT – กลับค่าตรรกะ (TRUE/FALSE)](https://www.thepexcel.com/functions/dax/logical/not-dax/)
- [HASONEVALUE – ตรวจสอบว่ามีค่าเดียวในบริบท](https://www.thepexcel.com/functions/dax/information/hasonevalue-dax/)
- [BLANK – คืนค่าว่าง (Empty Value)](https://www.thepexcel.com/functions/dax/other/blank-dax/)
- isblank-dax
- [IFERROR – คืนค่าแทนเมื่อเกิดข้อผิดพลาด](https://www.thepexcel.com/functions/dax/logical/iferror-dax/)
- [DIVIDE – ฟังก์ชัน DAX](https://www.thepexcel.com/functions/dax/math-and-trig/divide-dax/)
- [COALESCE – คืนค่าแรกที่ไม่เป็น BLANK()](https://www.thepexcel.com/functions/dax/logical/coalesce-dax/)
- [SELECTEDVALUE – ดึงค่าเดียวจาก Filter Context](https://www.thepexcel.com/functions/dax/filter/selectedvalue-dax/)
- [IF.EAGER – IF แบบประเมินค่าทั้งสองแขนง (eager)](https://www.thepexcel.com/functions/dax/logical/if-eager-dax/)
- [CALCULATE – ฟังก์ชันหลักของ DAX ที่ควบคุม Filter Context](https://www.thepexcel.com/functions/dax/filter/calculate-dax/)
- [FILTER – กรองตารางด้วยเงื่อนไขที่ซับซ้อน (Iterator Function)](https://www.thepexcel.com/functions/dax/filter/filter-dax/)
- [DATESYTD – ชุดวันที่ตั้งแต่ต้นปี (YTD) เพื่อใช้เป็นตัวกรองเวลา](https://www.thepexcel.com/functions/dax/time-intelligence/datesytd-dax/)
- [DATESMTD – ชุดวันที่ตั้งแต่ต้นเดือนถึงปัจจุบัน (MTD)](https://www.thepexcel.com/functions/dax/time-intelligence/datesmtd-dax/)
- [DATESQTD – ชุดวันที่ตั้งแต่ต้นไตรมาสถึงปัจจุบัน (QTD)](https://www.thepexcel.com/functions/dax/time-intelligence/datesqtd-dax/)

## แหล่งข้อมูลเพิ่มเติม

- [Microsoft Learn: IF function (DAX)](https://learn.microsoft.com/en-us/dax/if-function-dax) _(documentation)_
- [DAX Guide: IF](https://dax.guide/if/) _(documentation)_
- [SQLBI: Optimizing IF and SWITCH expressions using variables](https://www.sqlbi.com/articles/optimizing-if-and-switch-expressions-using-variables/) _(guide)_
- [SQLBI: Understanding BLANK in DAX](https://www.sqlbi.com/articles/understanding-blank-in-dax/) _(guide)_
- [Microsoft Learn: Best practices for using IF in DAX](https://learn.microsoft.com/en-us/power-bi/guidance/dax-avoid-avoid-filter-as-filter-argument) _(guide)_

---

_Source: [https://www.thepexcel.com/functions/dax/logical/if-dax/](https://www.thepexcel.com/functions/dax/logical/if-dax/)_
