Today's topic is one that almost everyone working with Power BI has heard of,
but hardly anyone can actually explain.
What exactly is DAX?
Is it just Excel formulas inside Power BI or is it something completely different?
Here's the thing, most people think DAX is basically Excel formulas with a different name,
but it isn't.
DAX is a whole different way of thinking about calculations.
If you try to treat it like Excel, you'll end up frustrated and confused,
wondering why your numbers don't add up.
By the end of this episode, you'll know what DAX actually is, why it matters,
and the core concepts you need to start using it with confidence.
Grab your coffee and let's dive in.
What exactly is DAX?
DAX stands for data analysis expressions,
and it's the formula language used inside Power BI, Power Pivot in Excel,
and SQL Server Analysis Services.
Think of it as the engine that powers your calculations behind the scenes.
DAX isn't new.
It's been around since Excel Power Pivot was introduced over a decade ago,
but with Power BI, it's become the go-to language for anyone serious about data analysis.
And here's what makes it different.
In Excel, you write formulas that work with individual cells.
Point to A1, multiply by B1, and you get a result for one cell.
DAX doesn't work that way.
It works with entire tables and columns at once.
You're not calculating one cell at a time.
Instead, you tell the engine, take this whole column of numbers and sum it up,
this or filter this entire table based on this condition.
So how do you picture it?
Imagine your building and office building.
Power BI gives you the structure, the floors, walls, and rooms.
That's your data model.
DAX is the wiring and the plumbing.
It's what makes everything work.
Without DAX, you have a building that looks nice, but has no electricity or running water.
With it, the lights turn on, the faucets work, and your reports actually respond when someone
clicks a slicer.
That responsiveness is the whole point.
DAX lets you create calculations that automatically react to filters and interactions.
Build one measure, and it shows the right number, whether someone's looking at total
sales by region, by product, or by month.
It just works.
But to use it well, you need to understand the two main ways to work with DAX.
Let's break those down.
The two worlds, calculated columns versus measures.
Today we are talking about two building blocks and DAXs, calculated columns and measures.
Most people think they are the same thing, they aren't.
Mixing them up is one of the most common mistakes I see.
A calculated column is static.
It adds a new column to your table.
It fills up during a refresh, and then it sits there.
It doesn't change until the next refresh.
Here's the simplest way to think about it.
Imagine a filing cabinet.
You put a piece of paper in a folder that paper has the customer's full name on it.
It doesn't matter if you look at the file today or next week.
The name is still there.
That is a calculated column.
A measure is completely different.
It doesn't sit in the table.
It lives in the memory of your report.
Every single time someone filters, slices or clicks a visual, the measure wakes up and recalculates.
Why does this matter?
If a user clicks a slicer for the North East region, a measure recalculates instantly.
A calculated column ignores the slicer.
It has to.
It is static.
Here is the simple rule.
If the number needs to change when someone clicks a button, use a measure.
If it is the same no matter what, a calculated column is fine.
Total sales should always be a measure.
If someone filters by region or by month, the total must update.
Customer full name is a column.
It never changes.
A slicer won't touch it.
Now, here is where most beginners get confused.
They create calculated columns for everything.
It feels natural because that is how Excel works.
But overusing columns bloats your model.
Your reports become slow.
Calculated columns create static numbers that ignore your users.
Measures are almost always the better choice.
They are dynamic.
They respond.
Once you understand this difference, you are ready for the real magic of DAX.
That magic is called filter context.
The big idea, filter context.
OK, we have our two building blocks.
Now let's talk about the engine behind them.
Every number you see in a Power BI report is calculated inside something called filter context.
It sounds complicated, but it is simple.
Filter context is just the set of filters active at that exact moment.
Where do those filters come from?
They come from the slices on your page.
They come from the visual you clicked.
They come from the page itself.
And the row you are looking at creates a filter context.
Here is why you should care.
When you write a measure like total sales, you are not telling it to look at the northeast
region in Q3.
You just tell it to add up the sales column.
That is it.
The measure doesn't know about regions.
It doesn't know about quarters.
It just adds up whatever rows are currently visible.
The filter context decides what is visible.
Imagine a spotlight.
Your whole data set is the room.
The filter context is the spotlight.
The measure is a camera taking a picture of exactly what the light hits.
Move the spotlight to the northeast region.
The measure recalculates, move it to Q3.
It recalculates again.
You didn't change the formula.
The context changed.
This confuses most people.
They write a measure.
It looks right in one visual.
Then they put it in a matrix with different filters and the number changes.
They think something is broken.
It is not broken.
That is exactly what a measure is supposed to do.
It is dynamic.
This is the real power.
You write one formula and it works for every possible filter combination in your entire
report.
One formula.
Infinite answers.
But you must be careful.
If you don't know what filters are active, you won't understand your number.
You need to trace the spotlight.
Get comfortable with filter context and you unlock the real power of DAX.
And that brings us to the star of the show.
The Calculate function.
The most important function.
Calculate.
Welcome back.
Today's knowledge nugget is about the single most important function in DAX.
It's called Calculate.
If you only master one function, make it this one.
Calculate.
Let's you control filter context instead of just accepting whatever filters are active.
Here's how normal measures work.
When you write a measure, it respects the current filter context automatically.
If someone selects 2024 from a slicer, your measure shows 2024 numbers.
If they choose the northeast region, it shows northeast numbers.
The measure responds to whatever filters are in play.
No extra work needed.
That's the default behavior.
But what if you need a number that ignores the current filters?
Maybe you want total sales for all regions right next to sales for the selected region?
Or you need last year's sales while someone is looking at this year.
In those cases, you can't rely on the default context.
You need to modify it.
That's exactly what Calculate does.
Calculate works by temporarily changing the filter context.
You give it an expression to calculate and then you give it one or more filters to apply.
It changes the context, runs the calculation and returns the result.
The original filter context stays untouched.
That's the magic.
The syntax is simple.
You write calculate, expression, filter one, filter two.
The expression is usually a measure you've already created.
The filters are the conditions you want to apply.
You can add as many filters as you need.
Let's see it in action.
Suppose you have a measure called total sales.
It shows sales for the selected period.
To show sales for the same period last year, you write calculate.
Total sales, same period last year calendar date.
That's all it takes.
Calculate takes your existing measure and shifts the date context back one year.
You get the comparison you need in one line.
Without calculate, you're stuck with whatever filter context exists.
With Calculate, you can override filters, add new ones, or remove existing ones.
You can request total sales for all products even when someone filters to a specific category.
You can pull sales from last month when the report shows this month.
The control is in your hands.
About 80% of advanced DAX relies on calculate.
Time intelligence, dynamic comparisons, custom aggregations, running totals, they all
use calculate under the hood.
Getting comfortable with this single function gives you enormous power over your reports.
But calculate works at the filter level.
What about row by row logic inside a measure?
That's where a different set of functions comes in.
Iterator functions when you need to think row by row.
So calculate handles filter level changes beautifully.
Sometimes you need to step inside a table and compute on each row individually inside a
measure.
A simple sum can't do that.
You need something that walks through the table row by row.
Here's a common situation.
You have a sales table with quantity and unit price in separate columns.
You want a measure that shows total revenue.
You can't just multiply some quantity by some unit price.
That multiplies the totals, not the individual rows.
You need to multiply each row's quantity by its unit price, then add up all those results.
That's row by row math.
Operator functions are built for this.
They're the functions that end in x, SUMX, average x, count x, minx, max.
The x stands for expression.
These functions take a table, walk through every single row, perform a calculation on each
row, and then aggregate the results into a single value.
For the revenue example, you write SUMX, sales, sales quantity, sales unit price.
The first argument is the table to iterate over.
The second argument is the expression to evaluate on each row.
SUMX goes row by row, multiplies quantity times price, and sums everything up.
One measure gives you the correct total revenue, simple and direct.
Use iterators whenever your calculation involves multiple columns from the same row.
Profit per line item, discounted price, weighted scores.
Anytime the math requires row by row logic inside a measure, an iterator is your tool, but
iterators have a performance cost.
They walk through every row, so overusing them on tables with millions of rows can slow
your reports to a crawl.
The simple rule only uses an iterator when you actually need row by row logic.
If a simple sum or average gives you the right answer, use that instead.
Your reports will thank you.
One more tip.
Sometimes a calculated column plus a simple sum is faster than SUMX.
If you create a calculated column that does the row level math once at refresh time and
then use a regular sum on that column, you avoid paying the iterator cost every time someone
views the report.
Test both approaches in your own data.
The fastest option depends on your model size and how often the data changes.
Use wisely.
Time intelligence made simple.
Now let's talk about one of the most requested features in Power BI, comparing time periods.
How are sales this month compared to last month?
How's the year tracking against last year?
These questions come up in almost every business report.
And DAX has functions built just for that.
Time intelligence functions handle year-to-day totals, same period last year, rolling averages
and month over month changes.
They're part of DAX, so you don't have to write complex filter logic from scratch, but
here's the catch.
Time intelligence functions need a proper date table.
Not just any date column from your fact table, you need a separate table with one row per
day covering your full date range with no gaps and it has to be marked as a date table
in your model.
Skip that step and the functions simply won't work.
Once you have that date table set up, the most useful functions are totaly TD, SAMHIPERIOD,
last year, data and dates between.
Total ITD is the simplest.
You write total ITD, total sales, calendar date.
And you get a running total from the start of the year through whatever date is in context.
Keep it in a line chart by month and you'll see that cumulative total grow as the year goes
on.
Same period last year does exactly what it sounds like.
It shifts the date context back one year, you pair it with calculate like this.
Calculate, total sales, same period last year calendar date.
Now you have last year's sales sitting right next to this year's numbers for easy comparison.
That add is even more flexible.
It lets you shift by days, months, quarters or years.
You can compare this quarter to the same quarter two years ago or see last month's numbers
by using minus one month.
That's the Swiss Army knife of time shifting.
The most common mistake people make is forgetting to mark their date table.
You can have a perfect date table with every day from 2020 through 2030.
But if you don't mark it as a date table in the model, the functions will return errors
or blanks.
It's a simple setting.
Right click the table, choose Mark as date table and pick the date column.
Do that once and everything starts working.
Another mistake is using time intelligence functions on a date column inside your fact table
instead of a dedicated date table.
The functions expect a continuous gap free date range and fact tables almost never have that.
So build a proper date table, market and your time intelligence will work smoothly.
Common beginner pitfalls.
Even with the right functions, beginners still hit common traps.
Let me walk you through the biggest ones so you can avoid them from day one.
The number one source of bugs and daxes is confusing row context with filter context.
Earlier we talked about how calculated columns create row context, evaluating one row at
a time while measures use filter context based on whatever filters are active.
beginners often write a measure as if it has access to individual rows, then wonder why
the results are wrong.
If your measure needs to see individual rows, use an iterator function.
If not, keep it simple.
The second big mistake is using calculated columns when a measure would work.
Calculated columns feel familiar because you can see the values in the table.
But every calculated column makes your model larger and refreshes slower.
Before adding one, ask yourself, does this value need to change when someone filters the
report?
If yes, it should be a measure.
Another trap is ignoring the data model itself.
Dax doesn't work in isolation.
It depends on the relationships between your tables.
If your model has weak relationships, wrong cardinality or missing join keys, your dax formulas
will fail silently.
You'll get numbers that look plausible but are actually wrong.
The fix isn't better, dax.
Fix your model first.
Then there's misusing calculate.
Beginners add multiple filters inside calculate without realizing they might cancel each
other out.
For example, a filter for sales for 2024 and another for sales from last year conflict,
and the result won't be what you expect.
Each filter inside calculate should have a clear purpose.
If you're not sure what it's doing, test it in isolation first.
One more common mistake is not using variables.
Variables declared with VR are let you store intermediate results and reuse them later
in the same measure.
Without them, you repeat the same calculation multiple times in one formula, making your
code harder to read, harder to debug and slower to run.
Get in the habit of using VR early.
It will save you hours of frustration and finally always validate your measures in different
contexts.
A measure that works perfectly in a card visual might break in a matrix total.
That's because the total row evaluates in a different filter context than the detail
rows.
Test your measures in tables and cards in matrices and with different slicer combinations.
If a measure holds up across all those scenarios, you know it's solid.
Putting it all together.
Alright, let's walk through a real example that pulls everything together.
Imagine you're building a sales report and you need to show three numbers.
Total sales for this period total sales for the same period last year and the growth
percentage between them.
First thing you need is a clean date table.
Go into your model, create a date table that covers your full date range, one row per day,
no gaps, then right click it, choose Marcus date table and pick the date column.
Do that once and every time intelligence function you write from there on will just work.
Next, write your base measure, call it total sales and type total sales, it will sum sales
amount.
That's the foundation and every other calculation will build on this one simple line.
Then you write the prior year measure, use calculate with same period last year.
It looks like this, prior year sales, epitome, calculate total sales, same period last year,
calendar date.
Now you've got current year sitting right next to last year, now the growth percentage.
Use divide to handle cases where last year sales might be zero and they will be.
Write it like this, growth percent is divide, total sales, prior year sales, prior year sales.
It safely returns a blank instead of an error if the denominator is zero.
That's the smart way to avoid crashes.
Now you have three reusable measures that work across any filter you throw at them.
Drop them into a table by product, by region, by month, they'll respond correctly every
single time.
That's the whole point.
Build on a clean model, master a handful of core functions and the rest falls into place.
So don't try to write complex stacks on day one, get your model right first, learn the
basics, measures, filter context, calculate.
And you'll solve most business problems with just a few lines of code.
So here's where we land.
You know what DAX is, why filter context matters and how calculate and iterator functions
do their thing.
You've seen the common traps and how to step around them.
And we walk through a real example that ties it all together.
The real power of DAX isn't about memorizing 100 functions.
It's about clean data modeling and a few core patterns.
Get the model right and the DAX becomes almost obvious.
Here's what I'd suggest you try, open power BI.
Build a simple model with a date table, a sales table and a product table.
Then write one measure each day for a week.
Start with total sales, add prior year sales, add growth percentage, then try a running
total.
By the end of the week, you'll be writing measures without even thinking about it.
That's how it clicks.
If this episode helped, subscribe and keep building that knowledge.
Next time we'll talk about debugging DAX when things go wrong.
Because they will.
And knowing how to fix them is half the battle.