Tableau Quiz: Debugging Calculations
10 questions · exam conditions
0:00
Debugging CalculationsQuestion 1 of 10

For each mark, an analyst needs to select a row-level measure based on segment and then total the selected values. The attempted calculation is CASE [Segment] WHEN "Consumer" THEN SUM([Sales]) WHEN "Corporate" THEN SUM([Profit]) ELSE 0 END, which produces an aggregate/non-aggregate error.

Which revision applies the segment logic at the correct level and then aggregates the result?

CASE ATTR([Segment]) WHEN "Consumer" THEN [Sales] WHEN "Corporate" THEN [Profit] ELSE 0 END
CASE [Segment] WHEN "Consumer" THEN SUM([Sales]) WHEN "Corporate" THEN SUM([Profit]) ELSE SUM(0) END
SUM(CASE [Segment] WHEN "Consumer" THEN [Sales] WHEN "Corporate" THEN [Profit] ELSE 0 END)
SUM(CASE ATTR([Segment]) WHEN "Consumer" THEN [Sales] WHEN "Corporate" THEN [Profit] ELSE 0 END)
← Back to quizzes

Tableau Quiz

Tableau Quiz: Debugging Calculations

Practice Debugging Calculations in Tableau with focused quiz questions that help you check what you know, review explanations, and build confidence with test-style prompts.

What this quiz covers

This quiz focuses on Debugging Calculations, giving you a quick way to practice the rules, question types, and explanations that matter most for Tableau.

How to use this quiz

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.

All questions

Question 1

For each mark, an analyst needs to select a row-level measure based on segment and then total the selected values. The attempted calculation is CASE [Segment] WHEN "Consumer" THEN SUM([Sales]) WHEN "Corporate" THEN SUM([Profit]) ELSE 0 END, which produces an aggregate/non-aggregate error.

Which revision applies the segment logic at the correct level and then aggregates the result?

  1. CASE ATTR([Segment]) WHEN "Consumer" THEN [Sales] WHEN "Corporate" THEN [Profit] ELSE 0 END
  2. CASE [Segment] WHEN "Consumer" THEN SUM([Sales]) WHEN "Corporate" THEN SUM([Profit]) ELSE SUM(0) END
  3. SUM(CASE [Segment] WHEN "Consumer" THEN [Sales] WHEN "Corporate" THEN [Profit] ELSE 0 END) (correct answer)
  4. SUM(CASE ATTR([Segment]) WHEN "Consumer" THEN [Sales] WHEN "Corporate" THEN [Profit] ELSE 0 END)
Explanation: Whenever you see a CASE expression mixing row-level fields with aggregate functions in Tableau, the key question is: where does the aggregation belong? Tableau requires that an expression be either entirely row-level or entirely aggregate — you cannot mix the two in the same calculation. The root problem in the original formula is that SUM([Sales]) and SUM([Profit]) are aggregates sitting inside a CASE that also references the row-level field [Segment]. Tableau sees aggregate and non-aggregate logic in the same expression and throws an error. The fix is to let CASE operate at the row level — selecting which raw value to pick per row based on Segment — and then wrap the entire expression in a single SUM() to aggregate afterward. That's exactly what C does: SUM(CASE [Segment] WHEN "Consumer" THEN [Sales] WHEN "Corporate" THEN [Profit] ELSE 0 END). The CASE runs first across individual rows, returning a row-level number, and SUM rolls those numbers up. This is correct. A is wrong because ATTR([Segment]) is itself an aggregate, which means you still have an aggregate-inside-non-aggregate conflict — and there's no outer SUM to finalize the result anyway. B attempts to keep aggregates inside the CASE and even adds SUM(0) on the ELSE branch, but mixing SUM([Sales]) and SUM([Profit]) inside a CASE that references a non-aggregated dimension still triggers the same mixed-aggregate error. D wraps a valid row-level CASE in SUM(), which sounds like C, but using ATTR([Segment]) inside an expression that's already being aggregated by the outer SUM creates another aggregate-nesting conflict. The study tip to remember: CASE goes inside SUM, not the other way around. Apply logic row-by-row first, then aggregate once on the outside.

Question 2

A department-level view shows cumulative sales over time. [Department Target] is identical for every row within a department. The calculation RUNNING_SUM(SUM([Sales])) / [Department Target] produces an aggregate/non-aggregate error.

Which revision correctly calculates cumulative sales as a proportion of the department target?

  1. RUNNING_SUM([Sales]) / ATTR([Department Target])
  2. RUNNING_SUM(SUM([Sales])) / ATTR([Department Target]) (correct answer)
  3. RUNNING_SUM(SUM([Sales])) / [Department Target]
  4. RUNNING_SUM(SUM([Sales]) / AVG([Department Target]))
Explanation: Whenever you encounter a table calculation mixed with a field reference in Tableau, ask yourself: is every component of the expression operating at the same level of aggregation? Tableau requires that you either fully aggregate a field or wrap it in a function like ATTR() — you can't mix a table calculation (which operates on already-aggregated values) with a raw field reference. In this scenario, RUNNING_SUM(SUM([Sales])) is a table calculation acting on an aggregate, which is correct. The problem is dividing by [Department Target] directly — Tableau sees this as mixing an aggregate expression with a non-aggregate field, triggering the error. The fix is wrapping [Department Target] in ATTR(), which returns the field's value when it's identical across all rows in the partition (exactly the case here, since the target is constant per department). That makes BRUNNING_SUM(SUM([Sales])) / ATTR([Department Target]) — the correct revision. A is wrong because RUNNING_SUM([Sales]) skips the required inner aggregation. RUNNING_SUM expects an aggregate expression as its argument; without SUM(), Tableau cannot evaluate it properly. C is the original broken formula — it still divides by the raw [Department Target] field, which is exactly what caused the aggregate/non-aggregate error in the first place. D embeds the division inside RUNNING_SUM, meaning it accumulates a ratio at each row rather than computing the cumulative sum first and then dividing once — logically incorrect for a proportion of a fixed target. Study tip: Remember that ATTR() is your bridge between a constant dimension value and an aggregate context — if a field is guaranteed to be the same across a partition, ATTR() safely lifts it into an aggregate expression without distorting the logic.

Question 3

An analyst wants to label each order as above or below the average order sales across the entire data source. The calculation IF [Sales] > AVG([Sales]) THEN "Above" ELSE "Below" END returns an aggregate/non-aggregate error.

Which revision resolves the error while preserving the intended row-level comparison?

  1. IF [Sales] > { FIXED : AVG([Sales]) } THEN "Above" ELSE "Below" END (correct answer)
  2. IF SUM([Sales]) > AVG([Sales]) THEN "Above" ELSE "Below" END
  3. IF [Sales] > WINDOW_AVG(SUM([Sales])) THEN "Above" ELSE "Below" END
  4. IF AVG([Sales]) > AVG([Sales]) THEN "Above" ELSE "Below" END
Explanation: Whenever you see a calculation mixing row-level fields like [Sales] with aggregate functions like AVG([Sales]), Tableau throws an aggregate/non-aggregate error because it can't resolve the two different levels of detail in the same expression. The fix requires bringing both sides of the comparison to the same level — and the cleanest way to do that while keeping the comparison row-level is a Level of Detail (LOD) expression. Answer A is correct because { FIXED : AVG([Sales]) } is a LOD expression that computes the grand average across the entire data source and returns it as a constant value attached to every row. This means [Sales] (row-level) is now being compared to a fixed scalar — no level-of-detail mismatch, and every individual order is correctly labeled relative to the overall average. Answer B aggregates [Sales] with SUM(), which eliminates the error but destroys the row-level intent — you're now comparing an aggregate to an aggregate, which makes sense only in a view with dimensions, not per-order. Answer C uses WINDOW_AVG, a table calculation that operates on aggregated query results, not on raw row-level data. It can't access [Sales] as a non-aggregate inside an IF statement and still doesn't solve the comparison at the row level. Answer D compares AVG([Sales]) to itself — both sides are identical, so the result is always "Above" (since the condition is always true), which is logically meaningless. A reliable study tip: when you need to compare a row-level field against a data-source-wide aggregate, reach for { FIXED : AGG([Field]) } — it collapses the aggregate into a constant that plays nicely at row level.

Question 4

A worksheet can contain both returned and non-returned orders in the same mark. An analyst needs the total sales from returned orders and writes IF [Status] = "Returned" THEN SUM([Sales]) ELSE 0 END, which produces an aggregate/non-aggregate error.

Which revision both compiles and produces the correct result for marks containing mixed order statuses?

  1. SUM(IF [Status] = "Returned" THEN [Sales] ELSE 0 END) (correct answer)
  2. IF ATTR([Status]) = "Returned" THEN SUM([Sales]) ELSE 0 END
  3. SUM(IF ATTR([Status]) = "Returned" THEN [Sales] ELSE 0 END)
  4. IF [Status] = "Returned" THEN SUM([Sales]) ELSE SUM(0) END
Explanation: Whenever you see a calculation that mixes a row-level comparison with an aggregate function in Tableau, ask yourself: where does the aggregation happen? Tableau requires that within a single expression, you can't mix unaggregated fields with aggregate functions at the same level — either everything gets aggregated, or nothing does. The correct fix is A: SUM(IF [Status] = "Returned" THEN [Sales] ELSE 0 END). Here, the IF condition evaluates row by row before aggregation occurs — each individual row either contributes its [Sales] value or contributes 0. Then SUM() wraps the entire expression, aggregating those row-level results cleanly. This correctly totals sales only from returned rows, even within marks that contain mixed statuses. B fails because it still mixes an aggregate (ATTR([Status])) with an aggregate (SUM([Sales])) inside an IF statement — but the deeper problem is logical: ATTR() returns a single value for the whole mark, so if a mark contains both returned and non-returned orders, ATTR([Status]) returns * (null/asterisk), making the condition false and returning 0 even when some sales were returned. It compiles but gives wrong results for mixed marks. C compounds the errors from B — using ATTR() inside a SUM() wrapper creates an aggregate-within-aggregate error, and the mixed-status logic problem remains. D attempts to fix the original by wrapping 0 in SUM(), but SUM([Sales]) inside an IF is still an aggregate nested inside a non-aggregate condition, reproducing the original error. Your study tip: always push the IF logic inside the aggregate function — SUM(IF ... THEN [field] ELSE 0 END) is the standard Tableau pattern for conditional aggregation.

Question 5

A developer is reviewing four Boolean calculated fields. [Sales Target Parameter] is a numeric parameter, while [Sales Target] is a numeric field in the data source.

Which calculation produces an aggregate/non-aggregate mixing error?

  1. SUM([Sales]) > [Sales Target Parameter]
  2. SUM([Sales]) > AVG([Sales Target])
  3. [Sales] > [Sales Target]
  4. SUM([Sales]) > [Sales Target] (correct answer)
Explanation: When working with calculated fields in Tableau, you need to understand the distinction between aggregate and non-aggregate expressions. An aggregate expression applies a function like SUM() or AVG() across multiple rows, while a non-aggregate expression evaluates at the row level. Tableau will throw a mixing error whenever you compare an aggregate value directly to a non-aggregate field in the same calculation — because they operate at fundamentally different granularities. Option D, SUM([Sales]) > [Sales Target], is the culprit. SUM([Sales]) is an aggregate, but [Sales Target] is a raw data source field — non-aggregate. Tableau cannot reconcile these two levels in a single expression, producing the mixing error. Option A is valid because [Sales Target Parameter] is a parameter, not a data source field. Parameters exist outside the data and are treated as constant scalar values, meaning they're compatible with aggregates without causing a mixing error. Option B is also valid — SUM([Sales]) and AVG([Sales Target]) are both aggregates, so they operate at the same level and compare cleanly. Option C avoids the error entirely because both [Sales] and [Sales Target] are non-aggregate row-level fields, keeping the calculation consistent. A useful rule of thumb: parameters play by different rules than fields. Parameters are always scalar and never cause mixing errors, no matter what you compare them to. When you see a field pulled directly from the data source sitting next to an aggregate function, that's your signal to flag a potential mixing error. On the exam, carefully check whether each operand is aggregate, non-aggregate, or a parameter before evaluating the calculation's validity.

Question 6

A view has exactly one region per mark. An analyst wants each mark's sales divided by total regional sales and writes SUM([Sales]) / { FIXED [Region] : SUM([Sales]) }. Tableau reports that aggregate and non-aggregate arguments cannot be mixed.

Which revision resolves the error without inflating the regional denominator when multiple rows underlie a mark?

  1. SUM([Sales]) / { FIXED : AVG([Sales]) }
  2. SUM([Sales]) / SUM({ FIXED [Region] : SUM([Sales]) })
  3. [Sales] / { FIXED [Region] : SUM([Sales]) }
  4. SUM([Sales]) / MIN({ FIXED [Region] : SUM([Sales]) }) (correct answer)
Explanation: Whenever you mix an aggregate expression like SUM([Sales]) with a Level of Detail (LOD) expression in a calculated field, Tableau requires the LOD result to also be wrapped in an aggregate function — otherwise you get the "cannot mix aggregate and non-aggregate" error. The key insight is that an LOD expression returns a row-level value from Tableau's perspective, even though it computed something at a fixed grain. To use it alongside an aggregate, you must aggregate it. The correct answer is D. Wrapping the LOD in MIN() satisfies the aggregation requirement. Because { FIXED [Region] : SUM([Sales]) } returns the same single value for every row belonging to a given region, MIN(), MAX(), and SUM() of that constant within the region all return that same constant — so the denominator is never inflated. You get the correct per-mark ratio: SUM([Sales]) / MIN({ FIXED [Region] : SUM([Sales]) }). A is wrong because { FIXED : AVG([Sales]) } computes a grand-average across the entire dataset, not the regional total — the denominator is entirely incorrect. B is wrong because SUM({ FIXED [Region] : SUM([Sales]) }) does solve the aggregation error syntactically, but SUM() of a constant repeated across multiple rows multiplies that constant by the row count, inflating the denominator whenever more than one row underlies a mark. C is wrong because [Sales] is a non-aggregate dimension value, making the numerator non-aggregate while the LOD is also non-aggregate — the aggregation error persists, and the ratio would be computed at row level rather than mark level. Your study tip: when an LOD appears in a calculation alongside an aggregate, always wrap the LOD in MIN() or MAX() (never SUM() or AVG()) to avoid unintentionally multiplying or averaging a fixed constant.

Question 7

A calculated field should label positive-profit records as Profit and all other records as No Profit. The developer writes IF [Profit] > 0 THEN "Profit" ELSE 0 END, and Tableau reports that the result types do not match.

Which revision best resolves the error while preserving the stated labeling requirement?

  1. IF [Profit] > 0 THEN STR([Profit]) ELSE 0 END
  2. IF [Profit] > 0 THEN "Profit" ELSE "No Profit" END (correct answer)
  3. IF [Profit] > 0 THEN 1 ELSE "No Profit" END
  4. IF SUM([Profit]) > 0 THEN "Profit" ELSE 0 END
Explanation: Whenever you see a calculated field producing a "result types do not match" error in Tableau, your first instinct should be to check whether every branch of your IF/THEN/ELSE statement returns the same data type. Tableau requires that all possible return values be consistent — all strings, all numbers, or all dates. You cannot mix types across branches. In the original formula, the THEN branch returns "Profit" (a string) while the ELSE branch returns 0 (an integer). That type mismatch is exactly what triggers the error. Option BIF [Profit] > 0 THEN "Profit" ELSE "No Profit" END — fixes this cleanly by returning a string in both branches, and it matches the stated requirement of labeling records as either "Profit" or "No Profit." This is the correct answer. Option A converts the profit number to a string with STR([Profit]) in the THEN branch, but the ELSE still returns 0 (an integer), so the type mismatch persists. It also fails the labeling requirement entirely. Option C has the same fundamental problem in reverse: 1 is an integer and "No Profit" is a string — still a type conflict, still broken. Option D wraps the condition in SUM(), which is an aggregation function and would cause a separate error when mixing aggregated and non-aggregated fields; it also keeps the 0 in the ELSE branch, leaving the original type mismatch unresolved. As a study tip, whenever you write an IF statement in Tableau, mentally audit every branch and ask: "Do all my return values share the same data type?" If not, use type-conversion functions like STR() or INT() to align them — just make sure every branch is converted, not just one.

Question 8

A developer attempts to recode regions with CASE WHEN [Region] = "East" THEN "E" WHEN [Region] = "West" THEN "W" ELSE "Other" END. Tableau reports a syntax error.

Which calculation correctly implements the intended logic using Tableau's CASE syntax?

  1. CASE [Region] WHEN "East" THEN "E" WHEN "West" THEN "W" ELSE "Other" END (correct answer)
  2. CASE WHEN [Region] THEN "East" = "E" WHEN "West" = "W" ELSE "Other" END
  3. CASE [Region] WHEN [Region] = "East" THEN "E" WHEN [Region] = "West" THEN "W" END
  4. CASE([Region], WHEN "East" THEN "E", WHEN "West" THEN "W", ELSE "Other")
Explanation: Tableau's CASE statement has two distinct syntactic forms, and mixing them up is one of the most common calculation errors you'll encounter. The form in the passage — CASE WHEN [Region] = "East" THEN... — is actually an IIF/IF-THEN style pattern, not valid CASE syntax in Tableau. Knowing the difference is exactly what this question tests. Tableau's CASE syntax requires you to place the field being evaluated immediately after the word CASE, then list only the comparison values (not full boolean expressions) after each WHEN. Answer A does this correctly: CASE [Region] WHEN "East" THEN "E" WHEN "West" THEN "W" ELSE "Other" END. Tableau compares [Region] to each value in sequence and returns the matching result — clean, valid, and complete. B is a structural inversion — it places the field after WHEN and tries to embed the comparison inside the THEN clause, which is backwards and nonsensical syntax. C uses the correct opening (CASE [Region]) but then breaks the rule by writing full boolean expressions ([Region] = "East") after WHEN, which is only valid in IF statements, not CASE. It also omits the ELSE clause. D wraps the entire expression in parentheses and uses commas as delimiters, resembling a function call — Tableau's CASE is a control-flow statement, not a function, so this syntax is entirely invalid. A useful mental shortcut: in Tableau's CASE, think "CASE [field], WHEN [value]" — you name the field once upfront, then only list values after each WHEN, never full conditions.

Question 9

An analyst wants to label an order as late when shipping occurred more than two days after ordering. The calculation IF DATEDIFF([Order Date], [Ship Date], "day") > 2 THEN "Late" ELSE "On Time" END produces an error.

Which revision uses the correct Tableau function syntax and preserves the intended date comparison?

  1. IF DATEDIFF("day", [Ship Date], [Order Date]) > 2 THEN "Late" ELSE "On Time" END
  2. IF DATEDIFF([Order Date], "day", [Ship Date]) > 2 THEN "Late" ELSE "On Time" END
  3. IF DATEDIFF("day", [Order Date], [Ship Date]) > 2 THEN "Late" ELSE "On Time" END (correct answer)
  4. IF DATEADD("day", [Order Date], [Ship Date]) > 2 THEN "Late" ELSE "On Time" END
Explanation: When working with Tableau's date functions, argument order is everything — getting it wrong causes errors even when your logic is sound. The function you need here is DATEDIFF, which calculates the difference between two dates. Tableau's required syntax is DATEDIFF(date_part, start_date, end_date) — the date part string comes first, followed by the earlier date, then the later date. The result is how many units of date_part elapsed from start to end. To detect late shipments, you want [Ship Date] minus [Order Date], meaning [Order Date] is your start and [Ship Date] is your end. That makes option CDATEDIFF("day", [Order Date], [Ship Date]) > 2 — the correct revision. It uses the right syntax and returns a positive number when shipping took more than two days, preserving the intended logic. Option A flips the two date fields, placing [Ship Date] as the start and [Order Date] as the end. This produces a negative number for late orders, so the > 2 comparison would never catch them — it silently reverses your logic. Option B keeps [Order Date] and [Ship Date] in roughly the right order but buries "day" in the middle, which violates the required argument sequence and produces an error. Option D uses DATEADD entirely, which adds a time interval to a single date rather than measuring the gap between two dates — it's the wrong function for this task altogether. A handy memory device: think "DATEDIFF = Part, Start, End" — the date part is always first, just like how you'd say "measured in days, from A to B."

Question 10

An analyst wants to calculate overall profit margin as total profit divided by total sales. The attempted calculation is SUM([Profit] / SUM([Sales])), and Tableau reports an aggregation error.

Which replacement resolves the error and preserves the required definition of overall profit margin?

  1. SUM([Profit]) / SUM([Sales]) (correct answer)
  2. SUM([Profit] / [Sales])
  3. AVG([Profit]) / SUM([Sales])
  4. SUM([Profit]) / AVG([Sales])
Explanation: Whenever Tableau throws an aggregation error, your first instinct should be to check whether you're nesting an aggregation inside another aggregation — that's almost always the culprit. The attempted formula SUM([Profit] / SUM([Sales])) tries to use SUM([Sales]) — an aggregate — inside another SUM(...). Tableau evaluates the inner SUM([Sales]) first, producing a single number, and then tries to divide each row-level [Profit] value by that aggregate before summing. Mixing row-level fields and aggregates within the same expression is illegal in Tableau's calculation engine, hence the error. Option A, SUM([Profit]) / SUM([Sales]), is the correct fix. It computes total profit and total sales independently, then divides the two aggregates — exactly the definition of overall profit margin. This is both syntactically valid and mathematically faithful to what the analyst intended. Option B, SUM([Profit] / [Sales]), avoids the nesting error, but it calculates a per-row profit ratio first and then sums those ratios. That produces a meaningless cumulative sum of individual margins, not an overall margin — a subtle but critical logical flaw. Option C uses AVG([Profit]) in the numerator, which divides total profit by the number of rows before dividing by total sales. This distorts the numerator and will not equal total profit divided by total sales. Option D mirrors that problem in the denominator: AVG([Sales]) is not the same as SUM([Sales]), so the ratio won't reflect true overall margin. Study tip: In Tableau, always keep aggregations at the same "level" — aggregate divided by aggregate. If you see a nested aggregate, that's your signal to restructure, not to work around it.