# Tableau LOD Expressions to DAX: FIXED, INCLUDE, and EXCLUDE

> Convert Tableau FIXED, INCLUDE and EXCLUDE LOD expressions to Power BI DAX. Working formulas using CALCULATE, ALLEXCEPT, REMOVEFILTERS and AVERAGEX.

- Canonical: https://getantares.io/tableau-lod-expressions-to-dax/
- Published: 2026-02-18
- Updated: 2026-07-27

---

Tableau Level of Detail (LOD) expressions have no one-to-one DAX equivalent, because Tableau controls aggregation grain with a keyword while Power BI controls it with filter context. Each keyword maps to a different DAX construct: **FIXED** becomes `CALCULATE` with `ALLEXCEPT` or `REMOVEFILTERS`, **INCLUDE** becomes an iterator such as `AVERAGEX` over `VALUES`, and **EXCLUDE** becomes `CALCULATE` with `REMOVEFILTERS` on the excluded column.

## Tableau LOD to DAX conversion table

Names below follow a standard star schema: a `Sales` fact table related to `Customer`, `Product`, and `Geography` dimensions.

| Tableau LOD | DAX equivalent | What it does |
| --- | --- | --- |
| `{FIXED [Region] : SUM([Sales])}` | `CALCULATE(SUM(Sales[Amount]), ALLEXCEPT(Sales, Sales[Region]))` | Aggregates at Region, ignoring the view and dimension filters |
| `{FIXED : SUM([Sales])}` | `CALCULATE(SUM(Sales[Amount]), REMOVEFILTERS())` | Grand total, ignoring everything |
| `SUM([Sales]) / MAX({FIXED [Region] : SUM([Sales])})` | `DIVIDE(SUM(Sales[Amount]), CALCULATE(SUM(Sales[Amount]), ALLEXCEPT(Sales, Sales[Region])))` | Percent of a fixed total |
| `{FIXED [Customer] : MIN([Order Date])}` | Calculated column on `Customer`: `CALCULATE(MIN(Sales[OrderDate]))` | An attribute of an entity, not a measure |
| `AVG({INCLUDE [Customer] : SUM([Sales])})` | `AVERAGEX(VALUES(Customer[CustomerKey]), CALCULATE(SUM(Sales[Amount])))` | Aggregates below the view grain, then re-aggregates up |
| `{EXCLUDE [Category] : SUM([Sales])}` | `CALCULATE(SUM(Sales[Amount]), REMOVEFILTERS(Product[Category]))` | Aggregates above the view grain |

## How FIXED converts

`FIXED` pins aggregation to the dimensions you name and ignores everything else in the view. In DAX the equivalent move is to clear filter context from every column except the ones you want to keep, which is what [ALLEXCEPT](https://learn.microsoft.com/en-us/dax/allexcept-function-dax) does.

There is one trap, and it accounts for most broken conversions. `ALLEXCEPT(Sales, …)` only clears filters on columns of the `Sales` table. A filter arriving from a related dimension table still propagates through the relationship, so a slicer on `Product[Category]` keeps shrinking the result even though the Tableau LOD ignored it. When the pinned dimension lives on a dimension table, combine [REMOVEFILTERS()](https://learn.microsoft.com/en-us/dax/removefilters-function-dax) with `VALUES(Geography[Region])` instead: the first clears the whole model, the second is evaluated in the outer filter context and puts the current region back.

It is also worth asking whether the LOD is a measure at all. A large share of FIXED expressions are attributes computed once per customer, order, or product — `{FIXED [Customer] : MIN([Order Date])}` is a cohort date. Modelled as a calculated column on the `Customer` table, `CALCULATE(MIN(Sales[OrderDate]))` is enough: inside a column, `CALCULATE` performs context transition and the relationship propagates the current customer. No `ALLEXCEPT` needed, and columns query faster than a measure re-evaluated per cell.

## How INCLUDE converts

`INCLUDE` pushes aggregation *below* the grain of the view, then re-aggregates the result upward. The DAX equivalent is an iterator over the included dimension, and the rule is mechanical: an `X` iterator over `VALUES` of the included column, wrapping the inner aggregate in `CALCULATE`. Match the iterator to the outer aggregate — `AVERAGEX` for `AVG`, `MAXX` for `MAX`, `MINX` for `MIN`. The inner `CALCULATE` is not optional: it triggers the context transition that makes each iterated customer filter the fact table.

One shortcut worth knowing: if the outer aggregate is `SUM`, the INCLUDE is almost always redundant, because summing per-customer sums returns the same total. INCLUDE only changes the answer when the outer aggregate is non-additive — average, max, min, or distinct count.

## How EXCLUDE converts

`EXCLUDE` drops a dimension that is present in the view, producing a coarser total on every row. In DAX you remove the filter on that one column and leave everything else alone.

If the excluded dimension is also on a slicer and the user's selection must still apply, use [ALLSELECTED](https://learn.microsoft.com/en-us/dax/allselected-function-dax) rather than `REMOVEFILTERS` — it restores the filter context from outside the visual instead of clearing it entirely. Note that `ALL(Product[Category])` used as a `CALCULATE` filter argument does the same job as `REMOVEFILTERS(Product[Category])`; the latter is the newer, unambiguous name and reads better in review.

## Why ALLEXCEPT does not always match FIXED

Tableau evaluates a worksheet through a fixed pipeline, and FIXED sits in the middle of it. DAX has no pipeline at all: there is only filter context, modified by `CALCULATE`. Reconciling the two is what makes LOD conversion hard, and it is why a formula-for-formula rewrite can look right and total wrong.

Tableau's [order of operations](https://help.tableau.com/current/pro/desktop/en-us/order_of_operations.htm) resolves extract filters first, then data source filters, then context filters, then FIXED, then dimension filters, then INCLUDE and EXCLUDE. What matters for conversion is which filters land before FIXED and therefore still affect it:

| Tableau filter | Affects a FIXED LOD? | How to reproduce in DAX |
| --- | --- | --- |
| Data source / extract filter | Yes | Filter the query in Power Query, not in the measure |
| Context filter | Yes | `ALLSELECTED` — keep what the user selected |
| Dimension filter (regular) | No | `ALLEXCEPT` or `REMOVEFILTERS` clears it |
| Measure filter | No — applied afterwards | Filter on the visual, not inside the measure |

The practical rule: a workbook that leaned on **context filters** converts to `ALLSELECTED`, and one that leaned on ordinary dimension filters converts to `ALLEXCEPT` or `REMOVEFILTERS`. The LOD formula alone will not tell you which — you have to look at how the worksheet filtered. Testing a converted measure with and without a slicer applied is the check that catches the difference.

## What Antares does with LOD expressions

Antares does not auto-translate LOD expressions, and that is deliberate: a silently wrong rewrite costs far more to find in UAT than a flagged one costs to write by hand. What the Analyzer does instead is find them. Every calculated field in the workbook is parsed and classified, and each LOD lands in the migration report as an explicit manual action with its type and the recommended DAX approach, rather than as a formula somebody discovers late.

That inventory is also what makes an estimate defensible — you know the LOD count and shape of an estate before committing to a date. [Run the free Analyzer](https://try.getantares.io) to get the breakdown for your own workbooks.

Related reading: [Tableau calculated fields to DAX](/tableau-calculated-fields-to-dax/) for the function-level mapping, and [Tableau table calculations to DAX](/tableau-table-calculations-to-dax/) for RUNNING_SUM, WINDOW_AVG, and RANK. Primary sources: Tableau's [LOD expression documentation](https://help.tableau.com/current/pro/desktop/en-us/calculations_calculatedfields_lod.htm) and Microsoft's [DAX function reference](https://learn.microsoft.com/en-us/dax/dax-function-reference).

## Related resources

- [Tableau to Power BI Migration Guide](/tableau-to-power-bi-migration/)
- [Calculated Fields to DAX](/tableau-calculated-fields-to-dax/)
- [Table Calculations to DAX](/tableau-table-calculations-to-dax/)
- [Sets to DAX Measures](/tableau-sets-to-dax-measures/)

## FAQ

### What is the DAX equivalent of a Tableau FIXED LOD expression?

CALCULATE with ALLEXCEPT. {FIXED [Region] : SUM([Sales])} becomes CALCULATE(SUM(Sales[Amount]), ALLEXCEPT(Sales, Sales[Region])). When Region sits on a dimension table rather than the fact table, use REMOVEFILTERS() combined with VALUES(Geography[Region]) so filters arriving through relationships are cleared too.

### Does ALLEXCEPT behave exactly like FIXED?

No. ALLEXCEPT only clears filters on columns of the table you pass it, so in a star schema a slicer on another dimension still reduces the result — something the Tableau LOD ignored. It also does not reproduce context filters, which FIXED respects; those map to ALLSELECTED instead.

### How do you convert an INCLUDE LOD expression to DAX?

Use an iterator over the included dimension. AVG({INCLUDE [Customer] : SUM([Sales])}) becomes AVERAGEX(VALUES(Customer[CustomerKey]), CALCULATE(SUM(Sales[Amount]))). Match the iterator to the outer aggregate — MAXX for MAX, MINX for MIN. The inner CALCULATE is required: it triggers the context transition.

### Does Antares convert LOD expressions automatically?

No, by design — a silently wrong rewrite costs more to find in UAT than a flagged one costs to write by hand. The Analyzer parses every calculated field, identifies each LOD and its type, and reports it as a manual action with the recommended DAX approach, so the work is known before the migration starts.
