Tableau • Calculations and Metrics

LOD & Filters — Combine LOD expressions with filters responsibly (context filters conceptually)

Master how Tableau's order of operations governs the interplay between LOD expressions and filters to produce correct analytics.

Tableau illustration with a dashboard presentation, data visualization, and database
Inside this lesson 10 sections 5 questions 8 figures

SECTION 1

Historical Context & Motivation

Before the advent of modern visual analytics platforms, analysts working with SQL-based reporting tools frequently encountered a frustrating limitation: any filter applied to a query would uniformly restrict every aggregation in the result set. If you filtered to show only the year 2023, every sum, average, and count was scoped exclusively to 2023 data — there was no straightforward way to display a 2023-filtered metric alongside a grand-total metric computed across all years. Achieving such mixed-granularity results required subqueries, common table expressions, or window functions that many business users found inaccessible. Tableau set out to democratize analytics, but as its user base grew more sophisticated, the demand for calculations that could transcend or restrict the visible level of detail became impossible to ignore.

2003 • Tableau Founded — VizQL Emerges

Pat Hanrahan and Chris Stolte commercialize VizQL, a visual query language that translates drag-and-drop actions into optimized database queries. Aggregation granularity is determined entirely by the dimensions on the shelf.

2009 • Table Calculations Introduced

Tableau adds table calculations (RUNNING_SUM, RANK, WINDOW_AVG), enabling post-aggregation computation. These operate after filters, so they cannot override filter scope — a significant limitation for cross-granularity analysis.

2015 • LOD Expressions Ship in Tableau 9.0

FIXED, INCLUDE, and EXCLUDE LOD expressions launch, allowing users to declare the exact grain of a calculation independently of the view. The relationship between LOD expressions and filters immediately becomes the most discussed topic in the Tableau community.

2018–Present • Context Filters & Pipeline Maturation

Tableau refines documentation around its order of operations (the 'query pipeline'). Context filters gain prominence as the mechanism to force dimension filters to apply before FIXED LOD computations, giving analysts fine-grained control over LOD scope.

The central question that LOD expressions address is deceptively simple: how do you compute a measure at a granularity that differs from what the current view shows, and how do filters interact with that computation? Understanding this interaction is not optional — misusing it produces silently incorrect numbers. The remainder of this lesson dissects Tableau's query pipeline, clarifies the role of context filters, and equips you to combine LOD expressions with filters responsibly.

SECTION 2

Core Principles & Definitions

Before diving into the mechanics, it is essential to formalize the vocabulary. A Level of Detail (LOD) expression in Tableau is a calculated field whose aggregation granularity is explicitly declared in the formula itself, rather than being inferred from the dimensions present on the visualization shelves. The three LOD keywords — FIXED, INCLUDE, and EXCLUDE — each establish a different relationship between the formula's grain and the view's grain. Meanwhile, Tableau processes filters in a strict sequence known as the order of operations (or query pipeline), and the position of an LOD expression within that pipeline determines which filters can affect it.

1

FIXED LOD

Computes a measure at exactly the specified dimension(s), ignoring the view grain entirely. Syntax: { FIXED [Dim] : AGG(Measure) }. Because FIXED is evaluated early in the pipeline, most dimension filters do NOT affect it unless promoted to context filters.
2

INCLUDE LOD

Adds the specified dimension(s) to the view's grain, producing a finer level of detail. Syntax: { INCLUDE [Dim] : AGG(Measure) }. INCLUDE is affected by dimension filters because it is evaluated at or after the dimension filter stage.
3

EXCLUDE LOD

Removes the specified dimension(s) from the view's grain, producing a coarser level of detail. Syntax: { EXCLUDE [Dim] : AGG(Measure) }. Like INCLUDE, it respects dimension filters.
4

Context Filter

A dimension filter that is explicitly promoted (via right-click → 'Add to Context') so that it executes before FIXED LOD expressions. Conceptually, a context filter creates a temporary, filtered dataset on which all subsequent computations — including FIXED — operate.
5

Order of Operations (Query Pipeline)

Tableau's deterministic sequence: Extract Filters → Data Source Filters → Context Filters → FIXED LOD → Dimension Filters → INCLUDE/EXCLUDE LOD → Measure Filters → Table Calculations. Each stage consumes the output of the prior stage.
✦

KEY TAKEAWAY

Think of the query pipeline as an assembly line in a factory. Raw materials (all rows) enter at one end. Each station (filter stage) removes or reshapes parts. A FIXED LOD expression is a worker stationed early on the line — it measures the material before most quality-control checkpoints (dimension filters) have run. If you want that worker to see only pre-approved material, you must move the quality checkpoint upstream by turning the filter into a context filter, effectively placing it before the FIXED station on the line.

SECTION 3

Visual Explanation — Tableau's Order of Operations

Tableau Query Pipeline — Order of Operations1Extract Filters2Data Source Filters3CONTEXT FILTERS(promoted dim filters)4FIXED LOD5Dimension Filters6INCLUDE / EXCLUDE LODMeasure / Table Calc⚠ Standard Dimension FilterExecutes at stage 5 — AFTERFIXED LOD is already computed✓ Promoted to Context FilterMoves to stage 3 — BEFOREFIXED LOD → constrains its scope
The diagram shows Tableau's query pipeline from left-to-right and top-to-bottom. Notice that context filters (stage 3) execute before FIXED LOD (stage 4), while standard dimension filters (stage 5) execute after. This ordering is the single most important concept in this lesson.

The diagram above is the conceptual backbone of every decision you will make when combining LOD expressions with filters. When you drag a dimension to the Filters shelf and set it to show only a subset of values, Tableau by default places that filter at stage 5 — after FIXED LOD computations have already been resolved. This means a { FIXED [Region] : SUM([Sales]) } calculation will sum sales across all categories even if a dimension filter restricts the view to a single category. To make the FIXED expression respect that filter, you must promote the filter to a context filter (stage 3), effectively shrinking the dataset before the FIXED computation fires. INCLUDE and EXCLUDE expressions, in contrast, sit at stage 6, meaning they naturally respect dimension filters without any promotion.

SECTION 4

How It Works — LOD Semantics and Filter Interaction

Formal Semantics of LOD Expressions

While Tableau does not expose SQL directly to the user, each LOD expression translates to a subquery or a window function under the hood. Understanding this translation clarifies why filter placement matters. Consider a view with [Category] on Rows and SUM([Sales]) on Columns. Adding a FIXED expression { FIXED [Region] : SUM([Sales]) } effectively generates a correlated subquery that groups by Region and joins the result back to every row in the main query. Because this subquery is logically evaluated before dimension filters, the subquery's WHERE clause includes only extract-level, data-source-level, and context-level filter predicates.

FIXED LOD — CONCEPTUAL SQL

SELECTRegion,SUM(Sales)FROMDataSourceWHERE[contextfilterpredicates]GROUPBYRegionSELECT Region, SUM(Sales) FROM DataSource WHERE [context_filter_predicates] GROUP BY Region

The WHERE clause contains only predicates from stages 1–3 (extract, data source, context). Standard dimension filter predicates are absent because they have not executed yet.

INCLUDE LOD — CONCEPTUAL SQL

SELECT[ViewDims],[IncludedDim],AGG(Measure)FROMfiltereddataGROUPBY[ViewDims],[IncludedDim]SELECT [ViewDims], [IncludedDim], AGG(Measure) FROM filtered_data GROUP BY [ViewDims], [IncludedDim]

filtered_data represents the dataset after stages 1–5 (including dimension filters). The INCLUDE expression then adds [IncludedDim] to the GROUP BY, producing a finer grain. Because dimension filters have already run, INCLUDE naturally respects them.

EXCLUDE LOD — CONCEPTUAL SQL

SELECT[ViewDims ExcludedDim],AGG(Measure)FROMfiltereddataGROUPBY[ViewDims ExcludedDim]SELECT [ViewDims \ ExcludedDim], AGG(Measure) FROM filtered_data GROUP BY [ViewDims \ ExcludedDim]

The backslash (\) denotes set difference. EXCLUDE removes [ExcludedDim] from the GROUP BY, yielding a coarser grain. Like INCLUDE, it respects dimension filters.

Context Filters — Conceptual Model

When you add a dimension filter to context, Tableau conceptually creates a temporary materialized table containing only the rows that pass the context filter predicate. All subsequent stages — including FIXED LOD — operate on this reduced table rather than the full data source. This is analogous to creating a CTE (Common Table Expression) in SQL: WITH ctx AS (SELECT * FROM DataSource WHERE [context_predicate]) and then running every other query against ctx. The performance implication is worth noting: because Tableau materializes this intermediate result, context filters can introduce latency on large datasets, but they guarantee semantic correctness when FIXED expressions must honor certain filter conditions.

⚠

Performance Note

Context filters cause Tableau to materialize a temporary table. On extracts (Hyper engine), the overhead is typically negligible. On live connections to row-store databases, context filters can significantly increase query time. Profile your workbook's performance before adding context filters liberally.

SECTION 5

Detailed Breakdown — Filter Types and Their Pipeline Position

Tableau supports several filter types, each occupying a specific slot in the query pipeline. Misidentifying which filter type you are using is a common source of incorrect LOD results. The table below provides a comprehensive classification, including each filter's pipeline stage, its interaction with FIXED LOD, and practical use cases.

Filter TypePipeline StageAffects FIXED?Affects INCLUDE/EXCLUDE?
Extract FilterStage 1 — earliestYesYes
Data Source FilterStage 2YesYes
Context FilterStage 3Yes ✓Yes
Dimension Filter (standard)Stage 5No ✗Yes
Measure FilterStage 7NoNo
Table Calc FilterStage 8 — latestNoNo

Filter types mapped to pipeline stages with LOD interaction flags

Scenario: FIXED [Region] : SUM([Sales]) with a Category FilterScenario A: Category = "Furniture" as Standard Dimension FilterAll Data → FIXED runs firstRegion | FIXED_SalesEast | $500K (all categories)West | $420K (all categories)→ Then dim filter hides non-Furniture rows→ But FIXED values remain unchanged!Result: FIXED ignores filter ✗Scenario B: Category = "Furniture" as Context FilterContext filter runs firstTemp table: only Furniture rowsRegion | FIXED_SalesEast | $180K (Furniture only)West | $150K (Furniture only)→ FIXED computed on pre-filtered dataResult: FIXED respects filter ✓Decision FlowchartUsing FIXED LOD?YesNeed dim filter to apply?YesAdd to ContextNoKeep as standard filter
Side-by-side comparison of a standard dimension filter (Scenario A) versus a context filter (Scenario B) on the same FIXED LOD expression. The decision flowchart at the bottom encodes the rule: if you need a dimension filter to constrain a FIXED computation, promote it to context.

The second diagram makes the practical implications concrete. In Scenario A, the FIXED expression calculates total sales per region across all categories because the Category filter has not yet executed when FIXED fires. The view shows only Furniture rows, but the FIXED value of $500K for East includes Technology and Office Supplies as well — a classic gotcha. In Scenario B, promoting Category to a context filter restricts the underlying data to Furniture rows before FIXED executes, yielding the correct $180K. The decision flowchart codifies a simple heuristic: whenever you combine FIXED LOD with a dimension filter and you intend the filter to constrain the FIXED computation, add the filter to context.

SECTION 6

Worked Example — Customer Cohort Analysis with Context Filters

Suppose you are analyzing the Superstore dataset. Your goal is to build a bar chart showing the number of customers whose first purchase fell in each year, but only for customers who have purchased items in the Technology category. The first-purchase year is computed via a FIXED LOD expression on [Customer ID].

Cohort Count by First-Purchase Year, Filtered to Technology Customers

  1. 1

    Step 1 — Define the FIXED LOD Expression

    Create a calculated field called [First Purchase Year] with the formula: { FIXED [Customer ID] : MIN(YEAR([Order Date])) }. This returns the earliest order year for each customer, regardless of the dimensions in the view.
    { FIXED [Customer ID] : MIN(YEAR([Order Date])) }
  2. 2

    Step 2 — Build the Initial View

    Place [First Purchase Year] (converted to a discrete dimension) on Columns and COUNTD([Customer ID]) on Rows. At this point, the chart correctly shows how many customers made their first purchase in each year across the entire dataset.
  3. 3

    Step 3 — Add a Category Filter (Standard) — Observe the Bug

    Drag [Category] to the Filters shelf and select only 'Technology'. The bar chart now shows only Technology rows, but the FIXED expression was computed before this filter. This means a customer who first purchased a Furniture item in 2018 but also bought Technology in 2020 will appear in the 2018 cohort, since the FIXED value was computed on unfiltered data. Worse, customers who never purchased Technology may still have their FIXED value computed, though they are excluded from COUNTD due to the dimension filter. The cohort counts and years may be subtly wrong.
    Bug: First-purchase year reflects all categories, not just Technology.
  4. 4

    Step 4 — Promote Category to a Context Filter

    Right-click the [Category] filter pill on the Filters shelf and select 'Add to Context'. The filter pill changes color (gray background in Tableau's UI) indicating it is now a context filter. Tableau materializes a temporary table of only Technology rows. The FIXED expression is now re-evaluated on this reduced dataset: { FIXED [Customer ID] : MIN(YEAR([Order Date])) } now only considers Technology orders when determining each customer's first-purchase year.
    Correct: First-purchase year now reflects the first Technology purchase.
  5. 5

    Step 5 — Validate

    Spot-check a specific customer. Suppose Customer ID 'AA-10315' first ordered Furniture in 2017 and first ordered Technology in 2019. Without the context filter, this customer appears in the 2017 cohort. With the context filter, they correctly appear in the 2019 cohort. The total customer count may also change, since customers who never bought Technology are now entirely excluded from the FIXED computation.

SECTION 7

Strengths, Limitations, and Common Pitfalls

AspectStrengthLimitation / Pitfall
FIXED LODComputes at an exact grain independent of the view; essential for cohort analysis, benchmarks, and ratios against a fixed denominator.Ignores standard dimension filters, leading to silently incorrect values unless context filters are used. Can cause confusion when the same calculated field is reused across worksheets with different filter configurations.
Context FiltersProvide a clean mechanism to scope FIXED expressions; conceptually simple (shrink the dataset first).Introduce temporary table materialization, which may degrade performance on live connections. Over-reliance can mask design issues — sometimes restructuring the LOD expression is preferable.
INCLUDE/EXCLUDENaturally respect dimension filters, reducing the need for context filters. More intuitive for adding or removing granularity relative to the view.Cannot define an arbitrary grain — they only add to or subtract from the view's dimensions. Not suitable when the desired grain has no relationship to the view.
Table Calc FiltersExecute last in the pipeline, so they hide marks without altering underlying computations — useful for top-N filtering without distorting LOD values.Cannot affect any LOD expression. Often misunderstood by users who expect them to behave like dimension filters.

Comparison of filter types and LOD interactions

⚠

COMMON PITFALL

The most insidious bug in Tableau dashboards occurs when a developer builds a worksheet with a FIXED LOD expression, tests it without filters, confirms correctness, and then later adds a dimension filter on a dashboard-level action or parameter-driven filter. The FIXED values silently remain unchanged, producing metrics that look plausible but are wrong. Always audit every FIXED expression in a workbook whenever new filters are introduced.

SECTION 8

Connection to Advanced Theory — Nested LOD, Parameters, and Sets

The interplay between LOD expressions and filters extends into more advanced Tableau patterns. Nested LOD expressions — where one LOD wraps another — follow the same pipeline rules, but the innermost expression is evaluated first, and its result is treated as a row-level value for the outer expression. Set-based filtering introduces another nuance: when a set is placed on the Filters shelf, it behaves as a dimension filter (stage 5), meaning it does not affect FIXED LOD unless the set filter is added to context. Similarly, parameter-driven filters implemented via calculated fields on the Filters shelf follow dimension filter semantics unless explicitly promoted.

PatternBasic Approach (this lesson)Advanced Extension
Scoping FIXEDPromote a single dimension filter to contextUse nested FIXED with an inner expression that pre-filters via a Boolean condition, avoiding context filters entirely
Dynamic granularityChoose INCLUDE or EXCLUDE based on static needsUse parameters to swap dimension references inside LOD expressions dynamically
Top-N within groupsTable calc filter to hide marksCombine FIXED with RANK table calc, then use set actions for interactive top-N that respects LOD
Cross-database LODSingle data source LODLOD across blended data sources (limited — FIXED only works within primary source)

From basic LOD-filter patterns to advanced techniques

As you progress into Tableau Prep, Tableau Server (now Tableau Cloud), and embedded analytics, the LOD-filter interaction remains unchanged — the query pipeline is a constant across all Tableau products. Building a solid mental model of this pipeline now will pay dividends when you encounter row-level security filters (which operate at the data source level, stage 2) or initial SQL (which runs before even extract filters). Each mechanism is simply another station on the same assembly line.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

Explain why a { FIXED [Customer ID] : SUM([Sales]) } expression is not affected when you filter the view to show only the 'West' region using a standard dimension filter. Reference the query pipeline stages in your answer.
Show answer
FIXED LOD expressions are evaluated at stage 4 of Tableau's query pipeline, while standard dimension filters operate at stage 5. Because stage 4 precedes stage 5, the FIXED expression computes SUM([Sales]) per Customer ID across all regions before the 'West' dimension filter removes non-West rows from the view. The result is that the FIXED values reflect total sales for each customer across every region, not just the West. To make the Region filter constrain the FIXED computation, you would need to promote it to a context filter (stage 3), which executes before stage 4.

Question 2: BASIC CALCULATION

You have the following calculated field: { FIXED [Region] : AVG([Profit]) }. Your view has [Category] on Rows and the FIXED field on Columns, with a standard dimension filter on [Segment] = 'Consumer'. What value does the FIXED field show — the average profit per region for Consumer only, or for all segments? What single change makes it respect the Segment filter?
Show answer
The FIXED field shows the average profit per region across all segments, because the Segment filter is a standard dimension filter (stage 5) and FIXED is computed at stage 4. The Category dimension on Rows does not alter the FIXED computation either, since the expression explicitly fixes on Region alone. To make the FIXED expression compute AVG([Profit]) for only the Consumer segment, right-click the Segment filter pill and select 'Add to Context'. This promotes the filter to stage 3, which precedes stage 4. Tableau will then materialize a temporary dataset containing only Consumer rows, and the FIXED expression will compute against that reduced dataset.

Question 3: INTERMEDIATE

You want to display each product's sales as a percentage of its category's total sales, and you want a dimension filter on [Region] to correctly restrict both the numerator and the denominator. Write the calculated field, specify which LOD type to use, and state whether a context filter is necessary.
Show answer
The calculated field is: SUM([Sales]) / { FIXED [Category] : SUM([Sales]) }. The denominator uses a FIXED expression to compute total sales per category. If [Region] is applied as a standard dimension filter, the numerator (SUM([Sales])) will correctly reflect only the filtered region because aggregations in the view respect dimension filters, but the FIXED denominator will still include all regions. This produces inflated denominators and thus deflated percentages. To ensure both the numerator and denominator are scoped to the selected region, you must promote the Region filter to a context filter. An alternative approach would be to use { EXCLUDE [Product Name] : SUM([Sales]) } as the denominator (assuming Product Name is the only sub-category dimension on the view), which would naturally respect the dimension filter since EXCLUDE operates at stage 6. However, this approach is fragile because it depends on the view's dimension configuration.

Question 4: APPLIED

A product manager asks you to build a dashboard with a Region quick filter. One chart shows average order value by sub-category; another shows average customer lifetime value (LTV), computed as { FIXED [Customer ID] : SUM([Sales]) }. The Region filter should scope both charts. Describe your filter design, including whether you use context filters, dashboard filter actions, or another approach, and justify your choice from a performance and correctness standpoint.
Show answer
The average order value chart uses a standard aggregation (AVG([Sales]) or SUM([Sales])/COUNTD([Order ID])), which naturally respects dimension filters. No special treatment is needed. The LTV chart, however, uses a FIXED expression on [Customer ID]. If the Region filter is applied as a standard dashboard filter, it will reach each worksheet as a dimension filter (stage 5) and will not affect the FIXED LTV computation. There are two correct approaches. First, on the LTV worksheet, add [Region] to the Filters shelf and promote it to a context filter; then use the dashboard's 'Use as Filter' action to drive that context filter. This is the simplest approach but may introduce latency because context filters materialize a temp table on every filter change. Second, restructure the LTV calculation to incorporate Region directly: { FIXED [Customer ID], [Region] : SUM([Sales]) }. This computes LTV per customer per region, so a standard dimension filter on Region correctly limits the output. However, this changes the semantics — a customer who buys in multiple regions will have separate LTV values per region, which may or may not match the product manager's intent. Clarify requirements before choosing.

Question 5: CRITICAL THINKING

Consider the expression { FIXED : COUNTD([Customer ID]) } (a FIXED expression with no dimension specified). This computes the grand total of distinct customers. Now suppose you have a standard dimension filter on [Category] = 'Furniture' and a context filter on [Region] = 'East'. What value does this expression return? Generalize your answer: describe the rule governing a FIXED expression with an empty dimension list and its interaction with each filter type.
Show answer
A FIXED expression with no dimensions specified computes a single scalar value at the table-level grain — conceptually, SELECT COUNTD([Customer ID]) FROM data. The context filter on Region = 'East' executes at stage 3, before FIXED (stage 4), so the FIXED expression operates on a dataset restricted to East region rows. The standard dimension filter on Category = 'Furniture' executes at stage 5, after FIXED, so the FIXED expression does not see it. Therefore, the expression returns the count of distinct customers who have any order in the East region — regardless of category. The Furniture filter only affects what marks appear in the view, not the FIXED value. The general rule: a FIXED expression with no dimensions is a grand-total computation over the dataset as it exists after stages 1–3 (extract, data source, and context filters). It is immune to dimension filters, and its value is replicated identically across every row in the view. This makes it useful for computing overall-dataset metrics (grand totals, overall averages) that can serve as denominators in percent-of-total calculations, but it requires careful context filter management to ensure the 'overall' scope matches user expectations.

SUMMARY

Summary

Summary

Tableau's LOD expressions — FIXED, INCLUDE, and EXCLUDE — allow you to compute measures at granularities that differ from the visualization's level of detail. The critical insight is that these expressions occupy specific positions within Tableau's order of operations (query pipeline): FIXED is computed at stage 4, before standard dimension filters (stage 5), while INCLUDE and EXCLUDE are computed at stage 6, after dimension filters. This ordering means FIXED expressions are immune to dimension filters by default.

To make a dimension filter constrain a FIXED expression, promote it to a context filter (stage 3), which materializes a temporary table before FIXED fires. Use context filters deliberately: they ensure correctness but may incur a performance cost on live connections. Always audit FIXED expressions whenever new filters are added to a workbook, and prefer INCLUDE or EXCLUDE when the desired granularity can be expressed as an addition to or subtraction from the view's dimensions, since these types naturally respect dimension filters without requiring context promotion.

Varsity Tutors • Tableau • LOD & Filters — Combine LOD expressions with filters responsibly (context filters conceptually)