What this quiz covers
This quiz focuses on Conditional Logic In Dax, giving you a quick way to practice the rules, question types, and explanations that matter most for Microsoft Power BI.
M = IF([Q]>0, IF([Rev]/[Q] > 10, "High", "Low"), "Zero"). Rev=400, Q=0 returns?
Microsoft Power BI Quiz
Practice Conditional Logic In Dax in Microsoft Power BI with focused quiz questions that help you check what you know, review explanations, and build confidence with test-style prompts.
This quiz focuses on Conditional Logic In Dax, giving you a quick way to practice the rules, question types, and explanations that matter most for Microsoft Power BI.
Try each quiz question before looking at the correct answer. Use the explanations to review missed ideas, then come back to similar questions until the pattern feels familiar.
M = IF([Q]>0, IF([Rev]/[Q] > 10, "High", "Low"), "Zero"). Rev=400, Q=0 returns?
M = SWITCH([Code], 1, [Sales]*2, 2, [Sales]). Code=3, Sales=100 returns?
In a measure, [A] || [B] && [C] is evaluated as:
M = SWITCH(TRUE(), [P]>100 && [Q], "High", [P]>50 || [Q], "Mid", "Low"). P=150, Q=FALSE returns?
A sales model contains the measure [Margin %]. A report must classify each result as follows: values of 30 percent or more are High, values from 15 percent through less than 30 percent are Medium, and all lower values are Low.
Which DAX measure provides the required classification?
Margin Band = SWITCH(TRUE(), [Margin %] >= 0.15, "Medium", [Margin %] >= 0.30, "High", "Low")Margin Band = SWITCH(TRUE(), [Margin %] >= 0.30, "High", [Margin %] >= 0.15, "Medium", "Low") (correct answer)Margin Band = SWITCH([Margin %], [Margin %] >= 0.30, "High", [Margin %] >= 0.15, "Medium", "Low")Margin Band = SWITCH(TRUE(), [Margin %] > 0.30, "High", [Margin %] > 0.15, "Medium", "Low")SWITCH(TRUE(), ...) in DAX, you're essentially building an if-else chain where each condition is evaluated in order, and the first one that returns TRUE wins. This means the order of your conditions matters critically — if a broader condition appears before a narrower one, it will "swallow" cases that should match the narrower condition.
Option B is correct because it checks the highest threshold first: if [Margin %] >= 0.30, return "High"; otherwise, if [Margin %] >= 0.15, return "Medium"; otherwise return "Low." Since 0.30 is tested before 0.15, a value like 0.35 correctly lands in "High" rather than being caught prematurely by the 0.15 condition.
Option A reverses the order — it checks >= 0.15 first. Any value of 0.30 or higher also satisfies >= 0.15, so it would incorrectly be classified as "Medium." The "High" branch would never be reached for values ≥ 0.30.
Option C misuses SWITCH syntax. The first argument to SWITCH should be the expression being compared — here it's [Margin %] — but the conditions are Boolean expressions, not scalar values equal to [Margin %]. This creates a type mismatch that won't evaluate as intended.
Option D uses strict greater-than operators (> 0.30 and > 0.15) instead of greater-than-or-equal-to. This means a value of exactly 0.30 would fall through to "Medium," and exactly 0.15 would fall through to "Low," both violating the requirements.
Your study tip: with SWITCH(TRUE(), ...), always order conditions from most restrictive to least restrictive — think of it like a waterfall where each level catches what the one above missed.A disconnected table named Threshold contains permissible margin rates. Users may select one rate in a slicer. If no rate or multiple rates are selected, the report must use 10 percent. A product passes when [Margin %] is greater than or equal to the applicable rate.
Which DAX measure meets the requirement?
Pass Status = IF([Margin %] >= SELECTEDVALUE(Threshold[Rate], 0.10), "Pass", "Fail") (correct answer)Pass Status = IF([Margin %] >= SELECTEDVALUE(Threshold[Rate]), "Pass", "Fail")Pass Status = IF([Margin %] >= MAX(Threshold[Rate]), "Pass", "Fail")Pass Status = IF([Margin %] >= MIN(Threshold[Rate], 0.10), "Pass", "Fail")SELECTEDVALUE. It returns the single selected value from a column — but crucially, it accepts an alternate result as a second argument, which is returned whenever zero or multiple values are selected.
Option A is correct because SELECTEDVALUE(Threshold[Rate], 0.10) does exactly what the requirement specifies: it returns the user's chosen rate when exactly one is selected, and falls back to 0.10 (10%) when nothing or multiple items are selected. The IF then compares [Margin %] against that resolved threshold, cleanly handling all scenarios.
Option B fails because it omits the alternate result argument. When no rate or multiple rates are selected, SELECTEDVALUE returns BLANK, and comparing any number to BLANK in DAX evaluates to BLANK — not "Fail". Your measure would silently produce a blank result instead of defaulting to 10%.
Option C uses MAX(Threshold[Rate]), which always returns the highest rate in the entire table regardless of slicer selection. This ignores the user's choice entirely and never applies the 10% default logic — it just picks the largest value unconditionally.
Option D attempts to pass 0.10 as a second argument to MIN, but MIN with two arguments is a scalar comparison function (it returns the smaller of two numbers) — not a filtered aggregation with a fallback. This is a different function signature entirely and doesn't replicate SELECTEDVALUE behavior.
Study tip: Memorize SELECTEDVALUE(column, alternate_result) as your go-to pattern for slicer-driven parameters with a default. The second argument is the fallback — if you omit it, blanks can silently corrupt your logic.The column Orders[Status] normally contains Open, Pending, or Closed, but new source-system values might be added later. A measure is evaluated where exactly one status is in context. It must return 1 for Open, 0.5 for Pending, 0 for Closed, and blank for any other status.
Which DAX expression correctly handles both the known statuses and future unmatched values?
Weight = SWITCH(SELECTEDVALUE(Orders[Status]), "Open", 1, "Pending", 0.5, "Closed", 0, BLANK()) (correct answer)Weight = SWITCH(TRUE(), "Open", 1, "Pending", 0.5, "Closed", 0, BLANK())Weight = SWITCH(SELECTEDVALUE(Orders[Status]), "Open", 1, "Pending", 0.5, BLANK(), "Closed", 0)Weight = IF(SELECTEDVALUE(Orders[Status]) = "Open", 1, IF("Pending", 0.5, IF("Closed", 0, BLANK())))SWITCH function, you need to understand both its syntax and how it handles unmatched cases — this question tests exactly that.
SWITCH(expression, value1, result1, value2, result2, ..., else) evaluates the expression once and matches it against each value in order. The final argument — with no paired value — is the else (default) result. Answer A is correct because it uses SELECTEDVALUE(Orders[Status]) as the expression, matches each known status to its weight, and places BLANK() as the trailing else argument. This means any future unrecognized status automatically returns blank, exactly as required.
Answer B is broken by a fundamental syntax error: SWITCH(TRUE(), ...) is a legitimate pattern for range-based conditions, but it requires each "value" argument to be a logical expression (like SELECTEDVALUE(...) = "Open"). Here, the values are just plain strings like "Open", which are always truthy constants — so the function would match "Open" immediately on the first comparison and always return 1, regardless of the actual status.
Answer C has the else clause in the wrong position. BLANK() is placed as a value to match against (the third value argument), not as the trailing default. DAX would look for a row where Status literally equals BLANK(), and "Closed" would become the orphaned else result — inverting the intended logic.
Answer D uses nested IF statements, but the inner conditions (IF("Pending", ...) and IF("Closed", ...)) are just non-empty strings, which DAX treats as TRUE, completely ignoring the actual status value.
As a study tip: always confirm that the last argument in SWITCH is unpaired — that's your else clause. Misplacing it is one of the most common DAX mistakes on this exam.A report classifies inventory items. An item is Critical when available quantity is below the reorder point and either the supplier is blocked or lead time exceeds 30 days. An item that does not meet all parts of that rule is Normal.
Which DAX measure applies the stated Boolean logic?
Inventory Status = IF([Available] < [Reorder Point] && [Supplier Blocked] || [Lead Days] > 30, "Critical", "Normal")Inventory Status = IF([Available] < [Reorder Point] || ([Supplier Blocked] && [Lead Days] > 30), "Critical", "Normal")Inventory Status = IF(([Available] < [Reorder Point] || [Supplier Blocked]) && [Lead Days] > 30, "Critical", "Normal")Inventory Status = IF([Available] < [Reorder Point] && ([Supplier Blocked] || [Lead Days] > 30), "Critical", "Normal") (correct answer)&& (AND) binds more tightly than || (OR). This means parentheses are essential whenever you need OR to be evaluated before AND — and this question is testing exactly that skill.
The business rule breaks down as: quantity below reorder point AND (supplier blocked OR lead time over 30 days). The AND connects the quantity condition to a compound OR condition. That compound OR must be grouped explicitly with parentheses, otherwise precedence will silently rewire your logic.
Option D — IF([Available] < [Reorder Point] && ([Supplier Blocked] || [Lead Days] > 30), "Critical", "Normal") — matches this perfectly. The parentheses force the OR to resolve first, then AND combines it with the quantity check.
Option A drops the parentheses entirely, so DAX evaluates it left-to-right with precedence as ([Available] < [Reorder Point] && [Supplier Blocked]) || [Lead Days] > 30. Any item with lead time over 30 days becomes Critical regardless of quantity — a completely different rule.
Option B uses OR at the top level: quantity-below-reorder or the supplier-and-lead combination. This flags items as Critical even when quantity is fine, as long as the supplier is blocked and lead time is long.
Option C groups quantity and supplier status under OR, then ANDs that with lead time. This requires lead time to always exceed 30 days for an item to be Critical, which contradicts the rule.
Study tip: When translating business rules into DAX, write out the logic in plain English first, then add parentheses around every OR clause before connecting it with AND — never rely on default precedence when mixing both operators.For each subscription row, [As Of Date], [Start Date], and [End Date] return scalar date values. A blank end date means the subscription has no scheduled end. Return Expired when a nonblank end date is before the as-of date, Not started when the start date is after the as-of date, and Active otherwise.
Which DAX measure correctly classifies subscriptions with and without end dates?
State = SWITCH(TRUE(), [End Date] < [As Of Date], "Expired", [Start Date] > [As Of Date], "Not started", "Active")State = SWITCH(TRUE(), [End Date] >= [As Of Date], "Expired", [Start Date] <= [As Of Date], "Not started", "Active")State = SWITCH(TRUE(), ISBLANK([End Date]) || [End Date] < [As Of Date], "Expired", [Start Date] > [As Of Date], "Not started", "Active")State = SWITCH(TRUE(), NOT ISBLANK([End Date]) && [End Date] < [As Of Date], "Expired", [Start Date] > [As Of Date], "Not started", "Active") (correct answer)SWITCH(TRUE(), ...) conditions matter enormously — and so does handling blank values correctly.
The business rule states that a subscription is Expired only when the end date is nonblank and earlier than the as-of date. This is exactly what D implements: NOT ISBLANK([End Date]) && [End Date] < [As Of Date]. Because SWITCH evaluates conditions top to bottom and stops at the first match, a blank end date correctly falls through to the next condition, where it can be classified as Not started or Active as appropriate.
A is tempting because the logic reads naturally, but it silently fails on blank end dates. In DAX, comparing a blank to a date (e.g., BLANK() < [As Of Date]) returns FALSE, so blank-end-date rows won't incorrectly trigger "Expired" — but only by coincidence. More critically, this approach doesn't explicitly guard against blanks, making the intent fragile and unclear. Actually, the real flaw in A is that it could misclassify edge cases depending on your data engine's blank-comparison behavior.
B reverses the comparison operators entirely — >= for expired and <= for not started — which produces logically backwards results. A date greater than or equal to the as-of date is not expired.
C goes wrong by including ISBLANK([End Date]) with an || (OR), meaning subscriptions with no end date would be labeled "Expired" — the opposite of the requirement.
Your study tip: whenever a field can be blank, always ask whether blank should trigger a condition or skip it. Use ISBLANK() with && (AND) to require a value, or || (OR) to catch empties — and know which behavior your rule demands.Customers qualify for a retention offer when they have either sales of at least 100,000 or year-over-year growth of at least 10 percent. In either case, their return rate must be below 5 percent.
Which condition should be used in an IF measure to implement the qualification rule?
[Sales] >= 100000 || [YoY Growth] >= 0.10 && [Return Rate] < 0.05([Sales] >= 100000 || [YoY Growth] >= 0.10) && [Return Rate] < 0.05 (correct answer)([Sales] >= 100000 && [YoY Growth] >= 0.10) && [Return Rate] < 0.05([Sales] >= 100000 || [YoY Growth] >= 0.10) || [Return Rate] < 0.05&& (AND) is evaluated before || (OR). This means the placement of parentheses is critical — and that's exactly what this question is testing.
The business rule has two parts: a customer must meet at least one revenue condition (high sales or strong growth), and they must also have a low return rate. This requires OR to be evaluated first, then AND applied to the result — which demands explicit parentheses around the OR clause.
B correctly captures this logic: ([Sales] >= 100000 || [YoY Growth] >= 0.10) && [Return Rate] < 0.05. The parentheses force the OR to resolve first, and then the AND gates the entire qualification on return rate. This matches the business rule precisely.
A is the classic operator-precedence trap. Without parentheses, DAX evaluates && before ||, so the expression actually reads as [Sales] >= 100000 || ([YoY Growth] >= 0.10 && [Return Rate] < 0.05). A customer with high sales alone would qualify regardless of their return rate — completely wrong.
C uses AND between the two revenue conditions, meaning a customer must have both high sales and strong growth to qualify. The business rule only requires one or the other, so this is far too restrictive.
D replaces the final && with ||, meaning a low return rate alone would qualify any customer — which contradicts the rule entirely.
Your study tip: whenever you see a mix of || and && in DAX, always ask yourself whether AND or OR should dominate. If OR must apply to a group, wrap it in parentheses — never assume DAX will read left-to-right.A sales-status measure must follow this priority: return No data when [Sales] is blank; otherwise return Loss when [Margin] is negative; otherwise return Met when [Sales] is at least [Target]; return Below for all remaining cases. [Target] can also be blank when sales data is missing.
Which DAX measure follows the required priority and avoids classifying missing data as Met?
Sales Status = IF([Sales] >= [Target], "Met", IF([Margin] < 0, "Loss", IF(ISBLANK([Sales]), "No data", "Below")))Sales Status = IF(ISBLANK([Sales]), "No data", IF([Sales] >= [Target], "Met", IF([Margin] < 0, "Loss", "Below")))Sales Status = IF(ISBLANK([Sales]), "No data", IF([Margin] < 0, "Loss", IF([Sales] >= [Target], "Met", "Below"))) (correct answer)Sales Status = IF([Margin] < 0, "Loss", IF(ISBLANK([Target]), "No data", IF([Sales] >= [Target], "Met", "Below")))IF statements, the order of conditions matters completely — each branch is only reached if all previous conditions were false. This question tests whether you can translate a priority-ordered business rule into the correct nesting sequence.
The required priority is explicit: blank sales → Loss → Met → Below. That means ISBLANK([Sales]) must be checked first, before any comparison involving [Sales] or [Target]. Option C does exactly this: it guards against blank sales immediately, then checks for a negative margin, then checks whether sales meets the target, and finally falls through to "Below." This matches the specification perfectly.
Option A is fatally flawed because it checks [Sales] >= [Target] before checking for blank sales. When [Sales] is blank, DAX treats it as zero — and if [Target] is also blank (also treated as zero), the comparison 0 >= 0 evaluates to TRUE, incorrectly returning "Met" instead of "No data." The blank-sales guard buried inside the third IF is never reached in that scenario.
Option B correctly handles the blank-sales case first, but then checks [Sales] >= [Target] before checking for a negative margin. This violates the stated priority — a loss situation would be classified as "Met" if sales happened to meet the target.
Option D starts with the margin check, bypassing the blank-sales guard entirely, and its "No data" logic is tied to a blank target rather than blank sales — a different condition altogether.
A reliable strategy: map the priority list directly to nesting order — the first rule in the spec becomes the outermost IF. If blank-checking isn't your first condition, missing data will almost always leak into another category.A budget-status measure must return No benchmark when [Budget] is blank or zero. For every other budget, return Above when [Actual] is at least 105 percent of budget, Below when [Actual] is at most 95 percent of budget, and Near otherwise.
Which DAX measure implements all conditions correctly?
Budget Status = IF(ISBLANK([Budget]) || [Budget] == 0, "No benchmark", SWITCH(TRUE(), [Actual] >= [Budget] * 1.05, "Above", [Actual] <= [Budget] * 0.95, "Below", "Near")) (correct answer)Budget Status = IF(ISBLANK([Budget]) && [Budget] == 0, "No benchmark", SWITCH(TRUE(), [Actual] >= [Budget] * 1.05, "Above", [Actual] <= [Budget] * 0.95, "Below", "Near"))Budget Status = IF(ISBLANK([Budget]) || [Budget] == 0, "No benchmark", SWITCH(TRUE(), [Actual] >= [Budget] * 0.95, "Above", [Actual] <= [Budget] * 1.05, "Below", "Near"))Budget Status = SWITCH(TRUE(), [Actual] >= [Budget] * 1.05, "Above", [Actual] <= [Budget] * 0.95, "Below", ISBLANK([Budget]) || [Budget] == 0, "No benchmark", "Near")|| (OR) to catch either condition that makes a budget invalid — blank or zero. If [Budget] passes that check, the SWITCH(TRUE()) pattern evaluates conditions top-to-bottom: ≥105% maps to "Above," ≤95% maps to "Below," and the implicit else returns "Near." The thresholds are also in the right direction: multiplying by 1.05 raises the bar for "Above" and multiplying by 0.95 lowers the bar for "Below."
Answer B uses && (AND) instead of || in the guard clause — meaning it only returns "No benchmark" when [Budget] is simultaneously blank AND zero. A blank value can never also equal zero in DAX's type system, so this condition can never be true. The guard is logically broken.
Answer C uses the correct || operator but swaps the multipliers: 0.95 is used for "Above" and 1.05 for "Below." This inverts the business logic entirely — a budget that's only 95% covered would incorrectly be labeled "Above."
Answer D skips the guard clause entirely and places the blank/zero check after the "Above" and "Below" conditions inside SWITCH. If [Budget] is zero, the percentage calculations execute first and could match before the "No benchmark" case is ever reached.
Study tip: On DAX logic questions, always verify three things: the correct operator (|| vs &&), the correct numeric thresholds, and the correct order of conditions.A measure named [Variance] can return blank, zero, or a nonzero number. The report must display No data for blank, On target for exactly zero, and Off target for any nonzero value.
Which DAX measure implements the requirement without treating a blank value as zero?
Result = SWITCH(TRUE(), [Variance] = 0, "On target", ISBLANK([Variance]), "No data", "Off target")Result = SWITCH(TRUE(), ISBLANK([Variance]), "No data", [Variance] == 0, "On target", "Off target") (correct answer)Result = SWITCH([Variance], BLANK(), "No data", 0, "On target", "Off target")Result = IF([Variance] <> 0, "Off target", IF(ISBLANK([Variance]), "On data", "No target"))SWITCH(TRUE(), ...), DAX evaluates each condition from top to bottom and returns the result of the first match. This means if a blank-sensitive check appears after a zero check, you risk misclassifying blank values — because in DAX, blank often coerces to zero in numeric comparisons.
Option B is correct precisely because it places ISBLANK([Variance]) first: SWITCH(TRUE(), ISBLANK([Variance]), "No data", [Variance] == 0, "On target", "Off target"). By checking for blank before checking for zero, you ensure a blank [Variance] never reaches the zero comparison, where it could be falsely matched.
Option A fails for exactly this reason — it checks [Variance] = 0 before ISBLANK([Variance]). Since blank coerces to zero in that comparison, a blank variance incorrectly returns "On target" instead of "No data."
Option C uses SWITCH([Variance], BLANK(), "No data", 0, "On target", "Off target"), which switches on the actual value of [Variance]. The problem is that BLANK() as a match value in this scalar form is unreliable — DAX does not consistently match blank this way, and this pattern is not the recommended approach for blank detection.
Option D has a logic error in the string labels: it returns "On data" and "No target" — clearly swapped — which alone disqualifies it, independent of any blank-handling issues.
Your study tip: always put ISBLANK() before zero comparisons in SWITCH(TRUE(), ...). Blank-before-zero is the correct order; reversing it is the most common trap on DAX conditional logic questions.A matrix uses Product[Category] and Product[Product] as nested row levels. A status measure must display Above or Below only when the product level is displayed. It must return blank at category subtotals and at the grand total. Some categories contain only one product.
Which DAX measure satisfies the requirement?
Status = IF(HASONEVALUE(Product[Product]), IF([Sales] >= [Target], "Above", "Below"), BLANK())Status = IF(ISFILTERED(Product[Product]), IF([Sales] >= [Target], "Above", "Below"), BLANK())Status = IF(ISINSCOPE(Product[Product]), IF([Sales] >= [Target], "Above", "Below"), BLANK()) (correct answer)Status = IF(ISINSCOPE(Product[Category]), IF([Sales] >= [Target], "Above", "Below"), BLANK())ISINSCOPE is designed for: it returns TRUE when the specified column is part of the current row grouping in the visual.
ISINSCOPE(Product[Product]) returns TRUE only when the product level is actively in scope — meaning the matrix is rendering a product row. At category subtotals and the grand total, Product[Product] is not in scope, so the function returns FALSE and the measure correctly returns BLANK(). This makes C the right answer.
A fails in the specific scenario the question flags: categories with only one product. When a category contains a single product, its subtotal row also has exactly one product value in context, so HASONEVALUE(Product[Product]) returns TRUE at the subtotal — displaying "Above" or "Below" where you want BLANK(). This is a classic trap.
B uses ISFILTERED, which returns TRUE whenever a direct filter is applied to Product[Product]. The problem is that filters applied at the product level can still be active at subtotal rows, so this doesn't reliably distinguish product rows from category subtotals.
D inverts the logic entirely. ISINSCOPE(Product[Category]) is TRUE at the category level and above, meaning the measure would show "Above"/"Below" at category subtotals — the opposite of what's required.
The study tip: memorize the distinction between HASONEVALUE (uniqueness of values), ISFILTERED (presence of a filter), and ISINSCOPE (current grouping level). Matrix-level visibility questions almost always call for ISINSCOPE.