Tableau Table Calculations in Databricks AI/BI: Running Totals, Ranks, and Window Functions
September 8, 2026
In Databricks AI/BI, a Tableau table calculation has two possible homes, computing at different moments. A calculated measure written with AGGREGATE OVER runs after the visualization groups its data. A window function written into the dataset SQL runs before dashboard field filters reach the result. Choosing the wrong home is the usual reason a converted total stops matching.
Where a table calculation runs in Databricks AI/BI
Tableau states the rule plainly: a table calculation "computes on the local data", and table calculations "do not consider any measures or dimensions that are filtered out of the visualization", per Tableau's documentation. The marks left in the view are the input.
The custom calculations page splits that in two. Scalar window functions use OVER and aggregate "before being joined back to the untransformed underlying table as a dimension". Aggregate window functions use AGGREGATE OVER and "compute windowed aggregations after visualization grouping has been applied".
With the dataset query, that makes three places for the arithmetic. Databricks points AGGREGATE OVER at calculations that should respect visualization filters, and the scalar OVER form at calculations "that must ignore all visualization groupings and filters". The third differs again: a window written into dataset SQL has already run when a field filter arrives, while a parameter substituted into that query changes what the window sees. Which control to reach for is on parameters in Databricks AI/BI. The docs do not cover every combination, so tie one number out at two filter states.
| Tableau | AI/BI custom calculation | Dataset SQL alternative |
|---|---|---|
RUNNING_SUM(SUM([Sales])) | SUM(Sales) AGGREGATE OVER (ORDER BY Date CUMULATIVE) | SUM(sales) OVER (ORDER BY Date |
WINDOW_AVG(SUM([Sales]), -2, 0) | No direct equivalent: divide a windowed SUM by the number of periods | AVG(daily_sales) OVER (ORDER BY day ROWS 2 PRECEDING) |
TOTAL(SUM([Sales])) | SUM(Sales) AGGREGATE OVER (PARTITION BY * EXCEPT (Product)), the EXCEPT list being whatever Compute Using totalled over; AGGREGATE OVER (ORDER BY Date ALL) is the other documented total | SUM(sales) OVER (PARTITION BY Region) |
SUM([Sales]) / TOTAL(SUM([Sales])), the Percent of Total quick table calculation | SUM(Sales) / (SUM(Sales) AGGREGATE OVER (PARTITION BY * EXCEPT (Region))) | SUM(Sales) / SUM(SUM(Sales)) OVER () |
LOOKUP(SUM([Sales]), -1) | No offset function; a one-period TRAILING range gives the previous period's aggregate | LAG(sales) OVER (ORDER BY Date) |
RANK, RANK_DENSE | RANK() and DENSE_RANK(), ranking rows rather than marks | Rank a pre-aggregated query |
| Top N on a table calculation | Not documented | QUALIFY RANK() OVER (PARTITION BY Region ORDER BY Sales DESC) = 1 |
How running totals and moving windows convert
Running totals convert almost mechanically. Databricks documents CUMULATIVE as the equivalent of RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, current mark included, as in Tableau's RUNNING_SUM.
Moving windows are where numbers drift. WINDOW_AVG(SUM([Sales]), -2, 0) averages three already aggregated marks. TRAILING and LEADING count time instead, in units of DAY, MONTH or YEAR, and they default to EXCLUSIVE, so add INCLUSIVE wherever the Tableau window ended at 0. Check what a gap does too: a mark-counted window steps over an empty period and a time-counted window counts it, the tolerance Databricks gives as the reason to prefer the time form.
One correction matters more than the syntax. AGGREGATE OVER re-evaluates the aggregate over every row in its frame, so AVG(Sales) across a trailing range returns the row-level mean, not the mean of the daily totals Tableau was averaging. Divide a windowed SUM by the number of periods instead, or pre-aggregate to one row per day in the dataset query and average that with a window frame such as ROWS 2 PRECEDING, which ends at the current row. An OFFSET clause shifts a whole range, so TRAILING 7 DAY OFFSET -1 YEAR reads a year back.
How ranks, LOOKUP and percent of total convert
Ranking needs the most care, because Tableau ranks the marks and the AI/BI ranking functions do not. All ranking and analytic window functions are supported in custom calculations, per the function reference, but they belong to the scalar OVER family that computes before grouping. Ranking what a viewer sees means ranking an already aggregated result in dataset SQL.
Direction is the second trap, and it inverts a leaderboard without erroring. Tableau's RANK and RANK_DENSE default to descending, so the largest value ranks 1, while the example in Databricks' QUALIFY reference ranks the smallest quantity 1. Add DESC to match. RANK_PERCENTILE defaults to ascending, lowest value at 0.
The documented percent-of-total pattern is SUM(Sales) / (SUM(Sales) AGGREGATE OVER (PARTITION BY * EXCEPT (Region))). The nested form SUM(Sales) / SUM(SUM(Sales)) OVER () also works for decomposable aggregates, though Databricks warns against it in a pivot table, where values get counted twice. LOOKUP with a negative offset has two answers: LAG at row level, or a one-period TRAILING range for an aggregated mark.
Why partitioning and addressing become PARTITION BY
Tableau gives every dimension in the view one of two jobs. "Partitioning fields break the view up into multiple sub-views", and the remaining addressing fields "determine the direction of the calculation". None of it lives in the formula text, and in AI/BI the partition is inherited rather than declared.
| Tableau setting | What it controls | Databricks AI/BI |
|---|---|---|
| Addressing (Compute Using) | The direction the calculation moves | ORDER BY inside AGGREGATE OVER or OVER |
| Partitioning (Restarting every) | Where the calculation resets | The visualization grouping picked up by PARTITION BY * |
Two limits bound custom calculations, as of September 2026. The custom calculations page caps them at 200 per dataset and notes that table visualizations take calculated dimensions but not calculated measures. The dashboard limits page puts chart rendering at 15,000 rows and tables at 100,000 rows before truncation; the visualization types page gives a lower table figure, so treat 100,000 as the ceiling and test.
What Antares does with table calculations
Addressing settings are the reason a table-calculation inventory cannot be built with a text search, and that is where a BI migration tool earns its keep on this route: the free Analyzer is deterministic, reads workbook metadata only, and lists which workbooks carry table calculations.
Where a partition cannot be resolved from the workbook, the Converter flags it for a person instead of guessing, because a guessed partition returns a plausible wrong number rather than an error. It is deterministic-first, with guardrailed and validated AI steps that can run against your own private LLM endpoints. Nothing in the Tableau environment changes. Try a sample conversion on a dashboard you know well.
Two neighbors finish the story: LOD expressions in Databricks SQL for pinned grains, and calculated fields to Databricks SQL for row-level formulas. Sequencing is on the migration guide, and the DAX version of this mapping is Tableau table calculations to DAX. Sources: Databricks' custom calculations, level of detail and window functions pages, and Tableau's table calculation functions.
← Back to the Tableau to Databricks Migration guide
Related Migration Resources
Frequently asked questions
What is the Databricks equivalent of RUNNING_SUM?
A calculated measure using the CUMULATIVE frame keyword: SUM(Sales) AGGREGATE OVER (ORDER BY Date CUMULATIVE). Databricks documents CUMULATIVE as the equivalent of RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, so the current mark is included, as it is in Tableau. The same frame works in dataset SQL, but it computes before dashboard field filters apply.
How do you write a moving average like WINDOW_AVG in Databricks AI/BI?
Not as a single keyword. WINDOW_AVG(SUM([Sales]), -2, 0) averages three already aggregated marks, while AGGREGATE OVER re-evaluates the aggregate across every row in its frame. Divide a windowed SUM by the number of periods, or pre-aggregate to one row per day in the dataset query and average that with a ROWS frame. TRAILING and LEADING also count time rather than marks and default to EXCLUSIVE.
Do Databricks AI/BI window calculations respect dashboard filters?
It depends on the syntax. Databricks recommends AGGREGATE OVER for window calculations that respect visualization filters, and the scalar OVER form for calculations that must ignore all visualization groupings and filters. A window inside dataset SQL runs before a field filter reaches it, though a parameter substituted into that query does change the result.
What replaces Tableau's Compute Using setting in Databricks AI/BI?
The visualization's own grouping, read through PARTITION BY * with an EXCEPT list, plus ORDER BY for direction. Tableau's addressing and partitioning choices live in the worksheet rather than the formula text, so plan on opening each workbook instead of counting formulas when you scope this work.