Module 1 · Power BI DAX
How DAX thinks
Set up the Kolanut model you'll use all course, write the base measures every report builds on, and learn the habits that keep a measure library trustworthy.
About 25 minutes
The problem
Kolanut Distribution's sales manager opens last month's Power BI report and sees three different revenue figures on three pages: ₦830.5m, ₦859.6m and ₦831.0m. One visual summed the list price, one summed revenue before discounts, and one summed a column somebody had rounded. Each was "Sum of something", dragged straight into a visual.
Nobody trusts the report now, and that's the real cost. A model with one Revenue measure, defined once and reused everywhere, can't disagree with itself.
In Power BI Fundamentals you wrote your first measures. This course goes deep: how DAX really evaluates a formula, CALCULATE, time intelligence, table functions, ranking, customer analytics and performance. It starts with a model and measures you can trust.
The concept
The model comes first
DAX is evaluated over the model: tables joined by relationships, with filters flowing from the "one" side to the "many" side. Kolanut's model is a small star schema:
| Table | Type | Rows | Relationship |
|---|---|---|---|
orders | Fact: one row per order line | 4,266 | the "many" side of everything |
customers | Dimension | 90 | customers[customer_id] 1 → * orders[customer_id] |
products | Dimension | 16 | products[product_id] 1 → * orders[product_id] |
Date | Dimension (calendar) | 730 | Date[Date] 1 → * orders[order_date] |
Filters flow downhill, from a dimension to the fact. Selecting "Lagos" in customers[region] filters orders. Selecting a product filters orders too. But nothing flows back up: filtering orders doesn't filter products. You'll meet the consequences of that in almost every lesson.
Measures, not dragged columns
Every number in a report should come from an explicit measure: written once, named clearly, formatted, and reused. Dragging a column into a visual creates an "implicit measure" that nobody can find, check or reuse.
Base measures first, then build on them
Write a handful of simple base measures, then build everything else from them. When the definition of revenue changes, you change one measure and the whole report follows.
Habits of a trustworthy measure library
- Keep measures in a dedicated
_Measurestable, in display folders (Sales, Customers, Time). - Name them as a manager would say them:
Revenue,Discount %,Active Customers. - Format every measure (₦ with thousands separators, % with one decimal place).
- Write a one-line description on each measure (Properties pane). It shows as a tooltip in the Data pane.
Example
Kolanut's base measures. Revenue is calculated from the order lines, so it doesn't depend on a column someone added in Power Query:
DAX
Revenue =
SUMX (
orders,
orders[quantity] * orders[unit_price] * ( 1 - orders[discount_pct] / 100 )
)
Gross Revenue =
SUMX ( orders, orders[quantity] * orders[unit_price] )
Discount Amount = [Gross Revenue] - [Revenue]
Discount % = DIVIDE ( [Discount Amount], [Gross Revenue] )
Order Lines = COUNTROWS ( orders )
Units = SUM ( orders[quantity] )
Active Customers = DISTINCTCOUNT ( orders[customer_id] )The three figures from the problem are now three named measures: Revenue (₦830.5m, what customers actually pay), Gross Revenue (₦859.6m, before discounts) and the difference between them, Discount Amount. Each one is clearly labelled, and none of them can be confused with another.
Walkthrough
- Download the sales dataset and load
orders.csv,customers.csvandproducts.csvinto Power BI Desktop. In Power Query, check thatorder_dateis a Date and thatquantity,unit_priceanddiscount_pctare Whole number. - Create the date table with Modeling → New table:
DAX
Date =
ADDCOLUMNS (
CALENDAR ( DATE ( 2025, 1, 1 ), DATE ( 2026, 12, 31 ) ),
"Year", YEAR ( [Date] ),
"Quarter", "Q" & ROUNDUP ( MONTH ( [Date] ) / 3, 0 ),
"Month Number", MONTH ( [Date] ),
"Month", FORMAT ( [Date], "mmm" ),
"Year Month", FORMAT ( [Date], "yyyy-mm" )
)- Mark it as a date table (Table tools → Mark as date table, column
Date), and sortMonthbyMonth Number. - In Model view, create the three relationships in the table above. Check each is one-to-many with a single cross-filter direction.
- Create a
_Measurestable (Home → Enter data, load an empty table), then add the seven base measures from the example. - Format them:
Revenue,Gross RevenueandDiscount Amountas currency with no decimals;Discount %as a percentage with one decimal place; the counts as whole numbers. - Put the measures into a display folder called
Sales(Model view → select the measures → Properties → Display folder), and giveRevenuethe description "What customers pay: quantity × price, after discount." - Check your model: a card with
Revenueshould show ₦830,541,245.
Practice
Practice
What is Discount % across all orders? One decimal place.
Practice
How many Active Customers placed orders in 2026?
Task
3 minPaste your Discount % measure exactly as you wrote it in Power BI. It should build on your other measures rather than repeating their formulas, and use DIVIDE.
Your work is checked for
- Named Discount %
- Uses DIVIDE, not the / operator
- Builds on existing measures in square brackets, such as [Discount Amount] and [Gross Revenue]
More practice
Optional drills. They don't count towards the certificate.
Drill · optional
What is Revenue for 2025? (A rounded figure is fine.)
Drill · optional
Legal data: load invoices.csv and write Billed = SUM(invoices[amount_ngn]). What is Billed across all invoices?
Check your understanding
Answer every question to check.