LOD Expressions are among the most powerful — and most misunderstood — features in Tableau. They let you compute aggregations at a different level of granularity than the current view, solving a whole class of analytics problems that are otherwise impossible with standard calculated fields or table calculations. Once you truly understand FIXED, INCLUDE, and EXCLUDE, your Tableau work will reach a completely different level.
Module 12 of 17 · Phase 3 Progress70%
🧠 Section 1
What Are LOD Expressions & Why They Exist
Every visualization in Tableau has a view level of detail — the combination of dimensions currently on Rows, Columns, or the Detail shelf. All measures are automatically aggregated at that level. This works perfectly for most charts, but sometimes you need an aggregation at a different level.
Consider this classic problem: you want to show each customer's orders alongside the customer's first-ever order date. The current view might be at the Order level, but the first order date is a customer-level computation. You can't just drag a date onto the view — that gives you the date for each individual order, not the customer's first date.
Before LODs, analysts had to either create database views or use messy workarounds. LOD Expressions solve this elegantly inside Tableau. The syntax is:
The curly braces {} are the LOD container. Everything inside them computes at a custom level — independent of (or relative to) what's on the view.
📌
The Mental Model
Think of LOD Expressions as running a separate, inner aggregation query that the outer view query can then reference. The LOD computes first (or in parallel), then the view uses that result. This two-pass mental model explains why LODs can reference dimensions not in the view and why they behave differently from table calculations.
📌 Section 2
FIXED LOD — The Most Commonly Used
A FIXED LOD computes at exactly the dimensions you specify, ignoring the current view dimensions entirely. It does not care what is or isn't on the view — it always locks to the dimensions you name.
// Real-world example — customer's first order date:
{ FIXED [Customer ID] : MIN([Order Date]) }
// Profit ratio fixed at the region level: SUM([Profit]) / { FIXED [Region] : SUM([Profit]) }
Practical Example: Profit Ratio by Region
Imagine your view shows Sub-Category vs Sales. You want to show each sub-category's profit as a percentage of its region's total profit. The region-total computation must be fixed at the region level regardless of how many sub-categories are visible.
1
Create the Regional Profit LOD
In a new calculated field called "Region Total Profit", write: { FIXED [Region] : SUM([Profit]) }. This always gives you the sum of profit for each region, no matter what else is in the view.
2
Create the Ratio Calculated Field
Create a second calc called "Profit % of Region": SUM([Profit]) / SUM([Region Total Profit]). Note you wrap the LOD in SUM() when using it in another aggregation context.
3
Build the View
Put Sub-Category on Rows, Region on Columns. Drag "Profit % of Region" to the view. Each cell shows what fraction of that region's total profit comes from that sub-category — exactly what we needed.
4
Verify the Logic
The FIXED LOD ensures the denominator doesn't change when you filter by Sub-Category. It stays anchored at the Region level. This is impossible to achieve cleanly with table calculations alone.
⚠️
FIXED and Filters — Important Interaction
FIXED LODs are computed before dimension filters but after data source filters and context filters. This means if you have a filter for [Region] = "West" on the view, the FIXED LOD will still compute for ALL regions unless you promote that filter to a Context Filter (right-click the filter → Add to Context). Keep this filter order in mind when results seem unexpected.
Zero-Dimension FIXED — Grand Total Ratio
You can use a FIXED LOD with no dimensions to compute a grand total. This fixes at the entire dataset level:
// Grand total profit across everything:
{ FIXED : SUM([Profit]) }
// Each row's profit as % of grand total: SUM([Profit]) / { FIXED : SUM([Profit]) }
This is particularly useful for executive summary views where you want to show each region's, product's, or segment's contribution to the overall business.
➕ Section 3
INCLUDE LOD — Adding Granularity
An INCLUDE LOD computes at the view's current level of detail plus the dimensions you specify. It makes the aggregation more granular than the view. The results are then re-aggregated for display in the view.
INCLUDE Syntax
{ INCLUDE [Dimension] : AGG([Measure]) }
// Average order value per customer (when view is at Segment level):
{ INCLUDE [Customer ID] : SUM([Sales]) }
The Classic INCLUDE Use Case: Average Order Value
You have a view showing Customer Segment on Rows. You want the average order value per customer. Simply doing AVG([Sales]) gives the average across all individual orders (i.e., average transaction amount), not the average per customer. INCLUDE solves this precisely:
// Step 1 — Compute total sales per customer at the customer level:
[Customer Sales] = { INCLUDE [Customer ID] : SUM([Sales]) }
// Step 2 — Average that in the view (now at Segment level): AVG([Customer Sales])
// This gives: for each Segment, the avg customer's total sales
💡
INCLUDE vs FIXED: When to Choose Each
Use INCLUDE when the extra dimensions you need are more granular than the view — you're adding detail. Use FIXED when you want to lock to specific dimensions completely regardless of the view. The key question: do you want the extra dimension to combine with the view dimensions (INCLUDE) or replace them entirely (FIXED)?
Scenario
View Level
LOD Type
LOD Expression
Avg sales per customer (by segment)
Segment
INCLUDE
{ INCLUDE [Customer ID] : SUM([Sales]) }
% of regional profit
Sub-Category
FIXED
{ FIXED [Region] : SUM([Profit]) }
Orders without specific product
Order
EXCLUDE
{ EXCLUDE [Product] : COUNT([Order ID]) }
First purchase date per customer
Order
FIXED
{ FIXED [Customer ID] : MIN([Order Date]) }
Revenue per order (view at category)
Category
INCLUDE
{ INCLUDE [Order ID] : SUM([Sales]) }
➖ Section 4
EXCLUDE LOD — Removing Granularity
An EXCLUDE LOD computes at the view's level of detail minus the dimensions you specify. It makes the aggregation less granular than the view — rolling up over the excluded dimensions.
EXCLUDE Syntax
{ EXCLUDE [Dimension] : AGG([Measure]) }
// Monthly sales without product-level breakdown (view at Product+Month):
{ EXCLUDE [Product Name] : SUM([Sales]) }
Practical Example: Running Total Benchmark
Suppose your view is broken down by both Month and Product Category. You want to compare each product's monthly sales against the total monthly sales across all products — a benchmark line. EXCLUDE removes the Category dimension, computing just the monthly total:
// Total sales for the month, ignoring product breakdown:
[Monthly Total] = { EXCLUDE [Category] : SUM([Sales]) }
// Share of each category within each month: SUM([Sales]) / SUM([Monthly Total])
💡
EXCLUDE Is Rare — But Powerful for Percent-of-Total
EXCLUDE is the least commonly used LOD type but shines for "percent of subtotal" calculations where the total should exclude a specific breakdown already in the view. It lets you compute a subtotal that spans one dimension while maintaining another. Many analysts never use EXCLUDE — once you understand it, you'll find niche but impactful use cases in almost every complex dashboard.
🔄 Section 5
LOD vs Table Calculations — Which to Use?
Both LOD Expressions and Table Calculations can compute aggregations beyond what the view directly shows, but they work in fundamentally different ways. Choosing the wrong one leads to incorrect results or performance problems.
Aspect
LOD Expressions
Table Calculations
Computed At
Database level (before rendering)
View level (after data is fetched)
Performance
Faster for large data
Slower; runs in Tableau engine
Filter Interaction
Complex (before/after filter order)
After all filters — simpler to predict
Reference Other Views
Cannot
Depends on view partition/address
Running Total
Possible but complex
Natural fit (RUNNING_SUM)
% of Grand Total
FIXED with no dimensions
TOTAL() function
Cohort Analysis
Ideal (FIXED per cohort)
Awkward
Rank
Possible
RANK() function is simpler
🎯
Decision Rule of Thumb
Use LOD Expressions when you need an aggregation that computes at a different grain than the view — particularly for cohort analysis, ratio-to-parent calculations, and first/last event per entity. Use Table Calculations when you need running totals, moving averages, rank within the current view, or percent of total where all visible data is the denominator. When in doubt and performance matters: prefer LOD.
Running Totals with LOD (Advanced Pattern)
While RUNNING_SUM() is the natural table calc choice for running totals, LODs can compute a version that survives filtering. Here is the pattern for a running profit total by order date that respects only context filters:
// Running profit up to the current date — LOD approach:
{ FIXED : SUM(IF [Order Date] <= MAX([Order Date]) THEN [Profit] END) }
This computes at the dataset level but conditionally sums only rows up to the max date in the current view context — effectively a running total that is stable across dashboard filter interactions.
🔧 Section 6
Troubleshooting LOD Expressions
LOD Expressions are a frequent source of confusion. Here are the most common problems and how to diagnose them.
Common Errors and Fixes
1
Error: "Cannot mix aggregate and non-aggregate arguments"
You're trying to use a LOD (which is an aggregate) alongside a non-aggregated field. Wrap both sides in the same aggregation. E.g., change SUM([Profit]) / {FIXED [Region] : SUM([Profit])} to SUM([Profit]) / SUM({FIXED [Region] : SUM([Profit])}).
2
LOD Returns Unexpected Nulls
Check whether the dimension you fixed on has any null values. A row with a null Customer ID will compute a separate LOD result for the null group. Add IFNULL([Customer ID], 'Unknown') to clean the dimension first, or filter out nulls using a data source filter.
3
FIXED Ignores My Filter
FIXED LODs run before dimension filters. If your filter is a normal dimension filter, it won't restrict the LOD's computation. Solution: right-click the filter pill → Add to Context. Context filters run before FIXED LODs and properly constrain them.
4
Wrong Granularity / Duplicated Values
If your LOD result seems duplicated or the totals are wrong, verify the LOD dimension exactly matches the grain you want. A { FIXED [Order ID] : SUM([Sales]) } gives sales per order — if your view is at row level (one row per order line), each order line will show the same order-total, which inflates SUM(). Use ATTR() or verify the view level.
5
Performance is Very Slow
LODs with many dimensions or on very large tables can be slow. Strategies: (a) Extract your data first, then LODs run on the fast .hyper engine; (b) Reduce the LOD to use fewer dimensions; (c) Pre-compute the LOD result in your database as a view and join it in; (d) Use a table calculation instead if the data volume in the view is manageable.
🧩
Nested LOD Expressions
You can nest LOD Expressions — a LOD inside a LOD. This is powerful for multi-level aggregations but can be complex to debug. Example: computing the average of fixed per-customer totals: AVG({ FIXED [Customer ID] : SUM([Sales]) }). The inner FIXED computes first, giving one row per customer. The outer AVG then averages those values. Nesting depth beyond 2 levels should be avoided for maintainability.
🔑 Key Concepts — Lesson 12
FIXED LOD
Computes at exactly the specified dimensions, ignoring the view. Ideal for cohort baselines, ratio denominators, and entity-level aggregations.
INCLUDE LOD
Computes at the view level PLUS additional dimensions. Results are then re-aggregated in the view. Use for more granular inner calculations like avg-per-entity.
EXCLUDE LOD
Computes at the view level MINUS specified dimensions. Useful for percent-of-subtotal where one dimension needs to be rolled up.
Context Filters
Context Filters run before FIXED LODs. When your FIXED result ignores a dimension filter, add that filter to Context to properly constrain the LOD computation.
🧠 Knowledge Check
1. You want to calculate the first (earliest) order date for each customer, to be used in a view that shows individual orders. Which LOD expression is correct?
2. A FIXED LOD expression appears to ignore a dimension filter on the view. What is the most common solution?
3. Your view is at the Segment level. You use: AVG({ INCLUDE [Customer ID] : SUM([Sales]) }). What does this calculate?
4. When is a Table Calculation preferable to an LOD Expression?
5. What does { FIXED : SUM([Sales]) } (a FIXED LOD with no dimensions) compute?
🏆
✅ Lesson Summary
What You Learned
📋
Lesson 12 — Key Takeaways
✅ LOD Expressions compute at a custom grain using { FIXED | INCLUDE | EXCLUDE [dims] : AGG([expr]) }
✅ FIXED ignores the view entirely and locks to the specified dimensions
✅ INCLUDE adds dimensions to the view grain for more granular inner aggregations
✅ EXCLUDE removes dimensions from the view grain for rolled-up subtotals
✅ FIXED LODs run before dimension filters — use Context Filters to constrain them
✅ Use Table Calculations for running totals/rank; use LODs for cross-level ratios and cohort baselines
You've mastered LOD Expressions — one of Tableau's most powerful and sought-after skills. Next: add statistical muscle to your dashboards with trend lines, forecasting, and confidence intervals.