Data Modeling Fundamentals
Build robust and efficient semantic models: relationships, cardinality, star schemas, normalization considerations, and sizing strategies.
Content
Calculated Columns vs Measures
Versions:
Watch & Learn
Calculated Columns vs Measures — The Great DAX Duel (a.k.a. Stop Confusing Them)
"One stores, one calculates at query time. One behaves like a sticky note, the other is a dynamic brain cell." — Your future BI model, probably
Hook: imagine your model is a kitchen
You're building a Power BI report and your dataset is the kitchen. Power Query is the prep chef who cleaned, chopped, and marinated the ingredients (you already learned that). Now you must decide: do we bake the dish ahead of time (calculated columns) or cook it to order when a guest sits at the table (measures)? Both feed people. Both can be delicious. But the timing, cost, and flexibility are very different.
This lesson builds on what you already know about primary keys and lookup tables and cardinality & cross-filter direction. Those relationships are your kitchen's plumbing — they determine how flavors (filters) flow between tables. Use that knowledge here.
TL;DR (for the impatient, but read the rest)
- Calculated columns: computed at refresh, stored in the model, contribute to model size, used like data fields in visuals, suitable for row-level data, and can be used as relationships or slicer fields.
- Measures: computed on the fly (at query time) in the context of filters, not stored, fast-ish if written well, essential for aggregated, dynamic values in visuals.
What they are, in plain (dramatic) English
Calculated Column
Definition: A column you add to a table with DAX that computes a value for every row when the model refreshes.
- Think: an oven-baked cookie — once it's baked, it's there until you refresh.
- Lives in the table, is materialized, increases model size.
- Useful when you need to group/sort/filter on that value or create a relationship.
Example DAX (in Sales table):
SaleAmount = Sales[Quantity] * Sales[UnitPrice]
This produces a SaleAmount for every sales row at refresh time.
Measure
Definition: A formula evaluated at query time that aggregates data according to the current filter context.
- Think: a barista making coffee to order — depends on who walked in, what they asked for, and the current context.
- Not stored; computed when visuals request the value; reacts to slicers/filters.
Example DAX:
Total Sales = SUMX(Sales, Sales[Quantity] * Sales[UnitPrice])
If you put this on a report, it recalculates for the current filters (date, product, region).
Why your previous lessons matter here
- Primary keys & lookup tables: Measures typically rely on well-structured lookup tables (like Date, Product) to create meaningful aggregates. Calculated columns sometimes need to reference the lookup side safely — remember relationships flow across keys.
- Cardinality & cross-filter direction: Measures obey filter propagation rules. If you have a many-to-many or one-to-many wrong, your measure may return unexpected results. Calculated columns are materialized so they don't depend on visual filter context — but they still reference relationships when evaluated at refresh.
- Power Query: If the value can be computed once (deterministic, row-level transformation), prefer computing in Power Query — it reduces model size and leverages M at ETL time. Use DAX calculated columns only when the calculation needs DAX-specific context.
Concrete scenarios — when to use which
Use a calculated column when:
- You need a field to slice or group by in visuals (e.g., bucket, category, custom sort column).
- You must create a relationship to another table based on the computed value.
- The calculation is row-by-row and won't explode model size (or it's precomputed in Power Query instead).
Use a measure when:
- You need aggregations that respond to filters (sum, average, percent of total, running totals).
- You want lightweight model size; the value should be computed on demand.
- Your calculation depends on filter context (like % of category, a running total by date).
Pitfalls and gotchas (aka the traps that make your dashboard lie)
- Creating many calculated columns = bigger model = slower refresh and higher memory usage.
- Using calculated columns for calculations that should be aggregated will lead to wrong numbers when visuals apply filters differently.
- Measures depend on correct relationships and cross-filter directions — a broken relationship means a measure that silently returns wrong results.
- Calculated columns are evaluated in row context at refresh; measures are evaluated in filter context at query time. These are different beasts — don't try to use one like the other without understanding contexts.
Quick comparison table
| Feature | Calculated Column | Measure |
|---|---|---|
| Computed when | Model refresh | Query time (visual render) |
| Stored in model | Yes | No |
| Affects model size | Increases | No |
| Uses | Slicing, relationships, row-level labels | Aggregation, dynamic calculations |
| Context | Row context (can use EARLIER, etc.) | Filter context (CALCULATE, ALL, VALUES) |
| Example | Product[CategoryKey] derived column | Total Sales % of Category |
Mini practical: Sales example
You have Sales (fact) and Product (lookup) tables. You want to show:
- Total revenue by product category (dynamic with slicers)
- A column in the Product table that flags "IsHighMargin" for internal grouping
Implementation:
- Calculate margin flag in Power Query or a calculated column in Product (it's a property of product, static):
IsHighMargin = IF(Product[MarginPercent] > 30, "Yes", "No")
- Compute revenue as a measure in Sales:
Total Revenue = SUMX(Sales, Sales[Quantity] * Sales[UnitPrice])
Now your visuals can slice by IsHighMargin and the Total Revenue measure will respect slicers and filters.
Best practices (your new commandments)
- Do as much as you can in Power Query (ETL) — it's usually cheaper than DAX computed columns.
- Prefer measures for aggregations and anything that should react to filter context.
- Use calculated columns only for grouping fields, keys, sorting, or when a measure can't do the job.
- Keep an eye on model size — remove unused calculated columns.
- Document why a calculated column exists — future-you will thank you.
Closing — the emotional truth
Calculated columns are the baked goods; measures are the made-to-order kitchen. Use the oven when you can, fire up the stove when you must. Combine them thoughtfully with well-designed relationships (your primary keys/lookup tables) and correct filter direction, and your Power BI model will be both performant and powerful.
Final question to ponder: if a calculation can be done in Power Query and will never change with slicers, why would you ever put it in DAX? (Hint: you probably shouldn't.)
Key takeaways:
- Calculated columns = stored, static at refresh.
- Measures = dynamic, evaluated per visual and filter context.
- Use Power Query first, then calculated columns for static model needs, and measures for everything dynamic.
Version note: this lesson assumes you already understand keys, lookup tables, and filter propagation. If your measures are misbehaving, revisit relationships and cardinality before blaming DAX.
Comments (0)
Please sign in to leave a comment.
No comments yet. Be the first to comment!