Move Tableau calculations into dbt models.
Separate row-level formulas from grouped aggregates before writing a dbt model. Inspect the actual workbook definitions and verify the rewritten query at the same grain.
Updated
Read locally in this browser.
Which formula belongs at row grain, and which is an aggregate?
This synthetic workbook contains Adjusted Revenue at row grain and Region Revenue as a grouped aggregate. Review their definitions before moving them into staging and mart models.
“Separate row-level calculations from aggregate metrics.”
Worked example · authored synthetic data
- Read the original fileUse the existing browser reader
- Check the definitionKeep the grouping and filter scope explicit
- Compute the resultUse the existing xmetric engine
- Review the evidenceRead the exact cells and query
Calculation or query in this example
Adjusted Revenue := [Revenue] * 0.9 Region Revenue := SUM([Adjusted Revenue])
Opening the labelled sample…
The browser is reading the sample’s workbook definitions.
Drop one file anywhere on this page. It is read in your browser; no file is uploaded.
Nothing is uploaded.
Read locallyThe original file stays in the browser.
Share deliberatelyMCP shares supported metadata and requested results with the chat host.
Separate actionsOnline saves and support uploads require their own actions.
How does this workflow work?
What is the direct answer to this workbook question?
Converting Tableau calculated fields to dbt models requires splitting workbook formulas into three layers: move row-level IF and string expressions into dbt staging models, refactor FIXED Level of Detail formulas into intermediate CTEs with explicit GROUP BY grains, and define ratio aggregations in your mart or semantic layer. Inspect the .twbx formulas first in the xmetric inspector.
Why should I separate calculation grains before dbt migration?
A Tableau workbook mixes three different calculation grains inside the same sidebar list: row-level expressions, view-dependent aggregations (SUM([Profit]) / SUM([Sales])), and grain-overriding Level of Detail ({ FIXED }) expressions.
If an analytics engineer or AI coding agent copies an aggregate ratio like SUM(profit) / SUM(sales) into a daily dbt mart table and later sums that column by month in a BI tool, the ratio of sums turns into a wrong sum of ratios. Classify every workbook formula by grain before writing your dbt SQL.
Which dbt layer fits each calculation type?
Keep row-level expressions in staging, explicit grouped calculations in intermediate models, and aggregate business metrics at their intended reporting grain.
| Tableau Calculation Type | Example in .twbx | Target dbt Layer | How to Write It in dbt |
|---|---|---|---|
| Row-level scalar | UPPER(TRIM([Email])) or DATEDIFF('day', [Created], [Closed]) | Staging (stg_*.sql) | Standard column expression in the SELECT list. Safe to materialize at the raw event or order grain. |
FIXED LOD expression | { FIXED [Customer ID] : MIN([Order Date]) } | Intermediate (int_*.sql) or Entity Mart (dim_customers.sql) | Pre-aggregate in a dedicated CTE grouped by the FIXED keys, then join back to the fact table. |
INCLUDE / EXCLUDE LOD | { INCLUDE [Order ID] : SUM([Sales]) } | Fact Mart (fct_orders.sql) | Build a mart table at the Order ID grain so any downstream chart can average it without an LOD. |
| Non-additive ratio | SUM([Profit]) / SUM([Sales]) | Semantic Layer / BI View (or xmetric) | Store the numerator (profit) and denominator (sales) in the dbt mart; divide at query time. |
How can I refactor a workbook calculation into dbt SQL?
Suppose you drop a legacy .twbx into the xmetric workbook inspector and find three nested calculated fields used on the executive revenue sheet:
// 1. [Clean Status] (Row-level)
IIF(ISNULL([Cancel Date]), 'Active', 'Churned')
// 2. [First Active Order] (FIXED LOD)
{ FIXED [Customer ID] : MIN(IF [Clean Status] = 'Active' THEN [Order Date] END) }
// 3. [Is New Customer Order] (Row-level referencing LOD)
[Order Date] = [First Active Order]What belongs in the staging model?
Move the row-level status cleanup into the staging model so every downstream model inherits it:
with source as (
select * from {{ source('raw', 'orders') }}
)
select
order_id,
customer_id,
order_date,
cancel_date,
amount,
case
when cancel_date is null then 'Active'
else 'Churned'
end as clean_status
from sourceWhat belongs in the intermediate or mart model?
Translate the FIXED LOD into a clean CTE and join it back on customer_id:
with orders as (
select * from {{ ref('stg_orders') }}
),
customer_first_active as (
select
customer_id,
min(case when clean_status = 'Active' then order_date end) as first_active_order_date
from orders
group by customer_id
)
select
o.order_id,
o.customer_id,
o.order_date,
o.clean_status,
o.amount,
c.first_active_order_date,
(o.order_date = c.first_active_order_date) as is_new_customer_order
from orders o
left join customer_first_active c
on o.customer_id = c.customer_idHow can I verify the dbt output against the workbook?
Never decommission a workbook until the new dbt table produces the exact same numbers as the original sheet:
- Inspect the original
.twbxin the xmetric workbook inspector in your browser to save the packaged data files and list the worksheet's formulas. You can also open the workbook in the xmetric app to rebuild the sheet on shelves. - Test the translated logic by running the original Tableau formula in the formula playground, which shows the equivalent SQL, or import your exported dbt output (CSV, Excel, or Parquet) into the xmetric app and explore it on shelves in your browser. Live Postgres and BigQuery connections remain coming.
- Compare the aggregated totals across dimensions to confirm that filter order of operations and null handling match 100%.
How do I know which Tableau calculated fields are actually worth migrating to dbt?
Most aged .twbx workbooks contain dozens of abandoned test calculations (Copy of Sales 2, Calc1). Drop your .twbx into the xmetric workbook inspector first to see which calculated fields are used on worksheets or referenced by other fields. It shows fields nothing uses and flags calculations that refer to a missing field, so you can skip them.
Should I move Tableau Table Calculations like RUNNING_SUM into dbt?
Usually no. A RUNNING_SUM(SUM([Sales])) depends on the exact date range and dimension filters a user selects at viewing time. Keep dynamic window calculations and ratios in your BI layer (you can test them in the xmetric formula playground and build them on shelves in the xmetric app) and keep grain-stable business logic in dbt.
Can xmetric open a .twb file from our Git repository without the data extract?
Yes. You can drop a .twb or .twbx file into the xmetric workbook inspector in your browser to inspect its calculated fields, sheets, dependencies, and data source structure for free. The inspector also reads a .pbix (report pages, visuals, fields per visual) and a zipped .pbip (tables, DAX measures, relationships), without running DAX.
List every formula in the workbook inspector before you write your first dbt model.
What data does this worked example use?
The initial view uses authored synthetic data, not customer data or a captured agent session.
The example record lists its file, calculation or SQL and expected values. The live browser result is computed by xmetric’s existing engine or workbook inspector. Samples are excluded from own-data activation reporting.